提交 b614d3d3 authored 作者: yanpeng's avatar yanpeng

Merge branch 'master' into yp-dev

...@@ -24,7 +24,7 @@ export function getIndustryHyly(params) { ...@@ -24,7 +24,7 @@ export function getIndustryHyly(params) {
}) })
} }
// 根据行业领域字典列表 // 行业领域字典列表
export function getHylyList() { export function getHylyList() {
return request({ return request({
method: 'GET', method: 'GET',
......
...@@ -14,7 +14,7 @@ const thinktankRoutes = [ ...@@ -14,7 +14,7 @@ const thinktankRoutes = [
} }
}, },
{ {
path: "/think-tank/:id", path: "/thinkTank/thinkTankDetail/:id",
name: "ThinkTankDetail", name: "ThinkTankDetail",
component: ThinkTankDetail, component: ThinkTankDetail,
meta: { meta: {
...@@ -22,7 +22,7 @@ const thinktankRoutes = [ ...@@ -22,7 +22,7 @@ const thinktankRoutes = [
} }
}, },
{ {
path: "/thinkTank/report/:id", path: "/thinkTank/reportDetail/:id",
name: "ReportDetail", name: "ReportDetail",
component: ReportDetail, component: ReportDetail,
meta: { meta: {
......
...@@ -272,193 +272,6 @@ ...@@ -272,193 +272,6 @@
</div> </div>
</div> </div>
</div> </div>
<!-- <div class="center-center1">
<div
class="center1-item"
:class="{ center1ItemActive: center1ActiveIndex === 0 }"
@click="handleClickCenter1Item(0)"
>
<div class="left">
<img src="./assets/images/p1.png" alt="" />
</div>
<div class="right">
<div class="name" :class="{ nameActive: center1ActiveIndex === 0 }">
{{ "唐纳德·特朗普任期" }}
</div>
<div class="time" :class="{ timeActive: center1ActiveIndex === 0 }">
{{ "2025.1.20-至今" }}
</div>
</div>
</div>
<div
class="center1-item"
:class="{ center1ItemActive: center1ActiveIndex === 1 }"
@click="handleClickCenter1Item(1)"
>
<div class="left">
<img src="./assets/images/p2.png" alt="" />
</div>
<div class="right">
<div class="name" :class="{ nameActive: center1ActiveIndex === 1 }">
{{ "乔·拜登任期" }}
</div>
<div class="time" :class="{ timeActive: center1ActiveIndex === 1 }">
{{ "2021.1.20-2025.1.20" }}
</div>
</div>
</div>
<div
class="center1-item"
:class="{ center1ItemActive: center1ActiveIndex === 2 }"
@click="handleClickCenter1Item(2)"
>
<div class="left">
<img src="./assets/images/p1.png" alt="" />
</div>
<div class="right">
<div class="name" :class="{ nameActive: center1ActiveIndex === 2 }">
{{ "唐纳德·特朗普任期" }}
</div>
<div class="time" :class="{ timeActive: center1ActiveIndex === 2 }">
{{ "2017.1.20-2021.1.20" }}
</div>
</div>
</div>
<div
class="center1-item"
:class="{ center1ItemActive: center1ActiveIndex === 3 }"
@click="handleClickCenter1Item(3)"
>
<div class="left">
<img src="./assets/images/p3.png" alt="" />
</div>
<div class="right">
<div class="name" :class="{ nameActive: center1ActiveIndex === 3 }">
{{ "贝拉克·奥巴马任期" }}
</div>
<div class="time" :class="{ timeActive: center1ActiveIndex === 3 }">
{{ "2013.1.20-2017.1.20" }}
</div>
</div>
</div>
</div> -->
<!-- <div class="center-center2">
<div class="center2-header">
<div class="center2-header-left">
<div class="left">
<div class="icon">
<img src="./assets/images/p1.png" alt="" />
</div>
</div>
<div class="right">
<div class="right-item1">{{ "唐纳德·特朗普" }}</div>
<div class="right-item2">
<div class="icon">
<img src="./assets/images/icon1.png" alt="" />
</div>
<div class="text">{{ "共和党" }}</div>
</div>
<div class="right-item3">{{ "美国第45任总统" }}</div>
<div class="right-item4">{{ "2025.1.20-至今" }}</div>
</div>
</div>
<div class="center2-header-right">
<div class="top">
<div class="top-box">
<div class="item1">{{ "本月发布" }}</div>
<div class="item2">
<div class="item2-1">{{ "1项" }}</div>
<div class="item2-2">{{ "/" }}</div>
<div class="item2-3">{{ "4项" }}</div>
</div>
</div>
<div class="top-box">
<div class="item1">{{ "今年发布" }}</div>
<div class="item2">
<div class="item2-1">{{ "7项" }}</div>
<div class="item2-2">{{ "/" }}</div>
<div class="item2-3">{{ "29项" }}</div>
</div>
</div>
<div class="top-box">
<div class="item1">{{ "任期内发布" }}</div>
<div class="item2">
<div class="item2-1">{{ "20项" }}</div>
<div class="item2-2">{{ "/" }}</div>
<div class="item2-3">{{ "96项" }}</div>
</div>
</div>
</div>
<div class="bottom">
<div class="icon">
<img src="./assets/images/tips-icon.png" alt="" />
</div>
<div class="text">{{ "涉华政令数量/政令总数" }}</div>
</div>
</div>
</div>
<div class="center2-mid" id="chartCalendar"></div>
<div class="center2-footer">
<div class="center2-footer-left">
<div class="header">
<div class="icon">
<img src="./assets/images/center2-header-icon2.png" alt="" />
</div>
<div class="text">{{ "主要内阁成员" }}</div>
</div>
<div class="main">
<div class="item" v-for="(item, index) in personList" :key="index">
<div class="item-left">
<img :src="item.avator" alt="" />
</div>
<div class="item-right">
<div class="item-right-box1">{{ item.name }}</div>
<div class="item-right-box2">{{ item.posi }}</div>
</div>
</div>
</div>
</div>
<div class="center2-footer-right">
<div class="header">
<div class="icon">
<img src="./assets/images/center2-header-icon1.png" alt="" />
</div>
<div class="tab-box">
<div
class="tab"
:class="{ tabActive: tabActiveIndex === index }"
v-for="(item, index) in list"
:key="index"
>
{{ item.title }}
</div>
</div>
<div class="right">
<div class="btn">
<img src="./assets/images/left-btn.png" alt="" />
</div>
<div class="btn">
<img src="./assets/images/right-btn.png" alt="" />
</div>
</div>
</div>
<div class="main">
<div class="main-item" v-for="(val, idx) in list[tabActiveIndex].data" :key="idx">
<div class="id">{{ idx + 1 }}</div>
<div class="info">
<div class="info-header">
<div class="title">{{ val.title }}</div>
<div class="tag">{{ val.tag }}</div>
</div>
<div class="info-content">
{{ val.content }}
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
<DivideHeader id="position3" class="divide3" :titleText="'数据总览'"></DivideHeader> <DivideHeader id="position3" class="divide3" :titleText="'数据总览'"></DivideHeader>
<div class="center-footer"> <div class="center-footer">
<div class="box3"> <div class="box3">
......
<template> <template>
<div class="wrap"> <div class="wrap">
<!-- <div class="box1"> <div class="box1">
<div class="box-header">
<div class="header-left"></div>
<div class="title">政令时序及战略里程碑</div>
<div class="header-right">
<img src="./assets/icons/header-icon.png" alt="" />
</div>
</div>
<div class="box1-main">
<div class="box1-line-box"></div>
<div
class="box1-item"
:class="{ box1ItemFooter: index % 2 }"
v-for="(item, index) in timeLineList"
:key="index"
>
<div class="point" :class="{ pointFooter: index % 2 }">
<img src="./assets/icons/box1-point.png" alt="" />
</div>
<div class="time" :class="{ timeFooter: index % 2 }">
{{ item.time }}
</div>
<div class="box1-item-header">
<div class="title">{{ item.title }}</div>
<div class="icon">
<img src="./assets/icons/box1-icon1.png" alt="" />
</div>
</div>
<div class="box1-item-content">
{{ item.content }}
</div>
</div>
</div>
<div class="box1-footer">
<div class="box1-footer-left">
<img src="./assets/icons/box1-icon2.png" alt="" />
</div>
<div class="box1-footer-center">
{{
"近两年美国AI领域核心政令与事件聚焦于安全治理与竞争领导权。拜登政府2023年10月签署首份AI行政令,强制要求强大AI系统进行安全测试并共享结果。2025年特朗普政府转向,签署《赢得竞赛:美国AI行动计划》,核心转为放松监管、加速创新与基础设施建设,并推动美国AI技术栈全球出口。其间,美国持续升级对华AI芯片出口管制,并积极介入全球AI安全治理议程"
}}
</div>
<div class="box1-footer-right">
<img src="./assets/icons/box1-icon3.png" alt="" />
</div>
</div>
</div> -->
<div class="box2">
<div class="box-header"> <div class="box-header">
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">相关政令关联分析</div> <div class="title">相关政令关联分析</div>
...@@ -60,13 +13,14 @@ ...@@ -60,13 +13,14 @@
</div> </div>
</div> </div>
</div> </div>
<div class="box2-main"> <div class="box1-main">
<div class="left"> <div class="left">
<div <div
class="left-item" class="left-item"
:class="{ leftItemActive: box2LeftActiveIndex === index }" :class="{ leftItemActive: siderActiveIndex === index }"
v-for="(item, index) in decreeList" v-for="(item, index) in siderList"
:key="index" :key="index"
@click="handleClickSider(index)"
> >
<div class="time">{{ item.time }}</div> <div class="time">{{ item.time }}</div>
<div class="title">{{ item.title }}</div> <div class="title">{{ item.title }}</div>
...@@ -76,14 +30,14 @@ ...@@ -76,14 +30,14 @@
<div class="right"> <div class="right">
<div class="info-box"> <div class="info-box">
<div class="info-left"> <div class="info-left">
<img :src="decreeList[box2LeftActiveIndex].img" alt="" /> <img :src="decreeInfo.img" alt="" />
</div> </div>
<div class="info-right"> <div class="info-right">
<div class="info-item"> <div class="info-item">
<div class="item-left">{{ "政令全称:" }}</div> <div class="item-left">{{ "政令全称:" }}</div>
<div class="item-right1"> <div class="item-right1">
<div class="item-right-text"> <div class="item-right-text">
{{ decreeList[box2LeftActiveIndex].totalTitle }} {{ decreeInfo.totalTitle }}
</div> </div>
<div class="item-right-icon"> <div class="item-right-icon">
<img src="./assets/icons/open-icon.png" alt="" /> <img src="./assets/icons/open-icon.png" alt="" />
...@@ -93,19 +47,19 @@ ...@@ -93,19 +47,19 @@
<div class="info-item"> <div class="info-item">
<div class="item-left">{{ "英文全称:" }}</div> <div class="item-left">{{ "英文全称:" }}</div>
<div class="item-right"> <div class="item-right">
{{ decreeList[box2LeftActiveIndex].eTotalTitle }} {{ decreeInfo.eTotalTitle }}
</div> </div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="item-left">{{ "签署时间:" }}</div> <div class="item-left">{{ "签署时间:" }}</div>
<div class="item-right"> <div class="item-right">
{{ decreeList[box2LeftActiveIndex].signTime }} {{ decreeInfo.signTime }}
</div> </div>
</div> </div>
<div class="info-item"> <div class="info-item">
<div class="item-left">{{ "签署总统:" }}</div> <div class="item-left">{{ "签署总统:" }}</div>
<div class="item-right"> <div class="item-right">
{{ decreeList[box2LeftActiveIndex].signPerson }} {{ decreeInfo.signPerson }}
</div> </div>
</div> </div>
</div> </div>
...@@ -113,12 +67,12 @@ ...@@ -113,12 +67,12 @@
<div class="list-box"> <div class="list-box">
<div class="list-header"> <div class="list-header">
<div class="icon"> <div class="icon">
<img src="./assets/icons/box2-list-header-icon.png" alt="" /> <img src="./assets/icons/box1-list-header-icon.png" alt="" />
</div> </div>
<div class="title">{{ "政令主要内容" }}</div> <div class="title">{{ "政令主要内容" }}</div>
</div> </div>
<div class="list-main"> <div class="list-main">
<div class="list-item" v-for="(val, idx) in decreeList[box2LeftActiveIndex].list" :key="idx"> <div class="list-item" v-for="(val, idx) in decreeInfo.list" :key="idx">
<div class="id">{{ idx + 1 }}</div> <div class="id">{{ idx + 1 }}</div>
<div class="title">{{ val.title }}</div> <div class="title">{{ val.title }}</div>
<div class="open"> <div class="open">
...@@ -129,7 +83,7 @@ ...@@ -129,7 +83,7 @@
</div> </div>
<div class="list-footer"> <div class="list-footer">
<div class="footer-left"> <div class="footer-left">
{{ `共${decreeList[box2LeftActiveIndex].list.length}项动态` }} {{ `共${decreeInfo.list.length}项动态` }}
</div> </div>
<div class="footer-right"> <div class="footer-right">
<el-pagination <el-pagination
...@@ -138,7 +92,7 @@ ...@@ -138,7 +92,7 @@
:current-page="currentPage" :current-page="currentPage"
background background
layout="prev, pager, next" layout="prev, pager, next"
:total="decreeList[box2LeftActiveIndex].list.length" :total="decreeInfo.list.length"
/> />
</div> </div>
</div> </div>
...@@ -151,130 +105,85 @@ ...@@ -151,130 +105,85 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import box2InfoImg from "./assets/icons/box2-info.png"; import box2InfoImg from "./assets/icons/box1-info.png";
const pageSize = ref(10); const pageSize = ref(10);
const currentPage = ref(1); const currentPage = ref(1);
const box1BtnActive = ref(1); const siderList = ref([
const timeLineList = ref([
{
time: "2025年1月",
title: "《AI扩散暂行最终规则》发布",
content: "拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。"
},
{
time: "2025年5月",
title: "特朗普宣布撤销拜登AI规则",
content: "特朗普政府宣布撤销拜登AI规则,计划推出新规。"
},
{
time: "2025年7月23日",
title: "特朗普签署EO 14320",
content: "特朗普签署EO 14320,推动美国AI技术栈出口。"
},
{
time: "2025年7月31日",
title: "中国网信办约谈英伟达",
content: "中国网信办约谈英伟达,要求就H20算力芯片漏洞后门安全风险问题进行说明。"
},
{
time: "2025年8月",
title: "英伟达H20发放出口许可证",
content: "美国商务部为4月份被实质禁售的英伟达H20发放出口许可证。"
}
]);
const decreeList = ref([
{ {
time: "2023", time: "2023",
title: "拜登人工智能政令", title: "拜登人工智能政令"
img: box2InfoImg,
totalTitle: "关于安全、可靠和可信地开发和使用人工智能的行政命令",
eTotalTitle: "Executive Order on the Safe, Secure, and Trustworthy Development and Use of Artificial Intelligence",
signTime: "2025年7月23日",
signPerson: "乔·拜登(Joe Biden)",
list: [
{
title: "要求强大AI系统开发者与政府分享安全测试结果(“红队测试”);制定生物合成筛查标准防范风险;建立AI生成内容鉴别标准"
},
{
title: "优先支持隐私保护技术(PET)研发;评估各机构如何收集和使用商业信息;制定评估隐私保护技术有效性的指南。"
},
{
title: "为解决算法歧视提供明确指导;确保刑事司法系统中AI使用的公平性;协调调查和起诉AI相关的民权侵犯行为。"
},
{
title: "推动医疗保健领域负责任地使用AI;创造资源支持教育工作者部署AI教育工具。"
},
{
title: "制定减轻AI对工人潜在危害的原则和最佳实践;编写AI对劳动力市场潜在影响的报告。"
},
{
title: "通过“国家AI研究资源”(NAIRR)试点促进研究;为小型开发者和企业家提供技术援助和资源;简化相关领域高技能人才的签证流程。"
},
{
title: "扩大在AI领域的国际合作;与国际伙伴和标准组织加速制定AI标准。"
},
{
title: "发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。"
},
{
title: "发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。"
},
{
title: "发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。"
}
]
}, },
{ {
time: "2023", time: "2023",
title: "拜登人工智能政令", title: "拜登人工智能政令"
img: "",
totalTitle: "",
eTotalTitle: "",
signTime: "",
signPerson: "",
list: []
}, },
{ {
time: "2025", time: "2025",
title: "特朗普撤销拜登AI规则", title: "特朗普撤销拜登AI规则"
img: "",
totalTitle: "",
eTotalTitle: "",
signTime: "",
signPerson: "",
list: []
}, },
{ {
time: "2023", time: "2023",
title: "美国AI行动计划", title: "美国AI行动计划"
img: "",
totalTitle: "",
eTotalTitle: "",
signTime: "",
signPerson: "",
list: []
}, },
{ {
time: "2024", time: "2024",
title: "对中国AI芯片限制", title: "对中国AI芯片限制"
img: "",
totalTitle: "",
eTotalTitle: "",
signTime: "",
signPerson: "",
list: []
} }
]); ]);
const siderActiveIndex = ref(0);
const handleClickSider = index => {
siderActiveIndex.value = index
}
const decreeInfo = ref({
img: box2InfoImg,
totalTitle: "关于安全、可靠和可信地开发和使用人工智能的行政命令",
eTotalTitle: "Executive Order on the Safe, Secure, and Trustworthy Development and Use of Artificial Intelligence",
signTime: "2025年7月23日",
signPerson: "乔·拜登(Joe Biden)",
list: [
{
title: "要求强大AI系统开发者与政府分享安全测试结果(“红队测试”);制定生物合成筛查标准防范风险;建立AI生成内容鉴别标准"
},
{
title: "优先支持隐私保护技术(PET)研发;评估各机构如何收集和使用商业信息;制定评估隐私保护技术有效性的指南。"
},
{
title: "为解决算法歧视提供明确指导;确保刑事司法系统中AI使用的公平性;协调调查和起诉AI相关的民权侵犯行为。"
},
{
title: "推动医疗保健领域负责任地使用AI;创造资源支持教育工作者部署AI教育工具。"
},
{
title: "制定减轻AI对工人潜在危害的原则和最佳实践;编写AI对劳动力市场潜在影响的报告。"
},
{
title: "通过“国家AI研究资源”(NAIRR)试点促进研究;为小型开发者和企业家提供技术援助和资源;简化相关领域高技能人才的签证流程。"
},
{
title: "扩大在AI领域的国际合作;与国际伙伴和标准组织加速制定AI标准。"
},
{
title: "发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。"
},
{
title: "发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。"
},
{
title: "发布政府机构使用AI的指南;加快招聘AI专业人才并为相关领域员工提供培训。"
}
]
});
const box2LeftActiveIndex = ref(0);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.wrap { .wrap {
height: 100%;
overflow: hidden;
.box-header { .box-header {
height: 56px; height: 56px;
display: flex; display: flex;
...@@ -323,164 +232,13 @@ const box2LeftActiveIndex = ref(0); ...@@ -323,164 +232,13 @@ const box2LeftActiveIndex = ref(0);
} }
} }
.box1 { .box1 {
margin: 27px auto 16px;
width: 1600px;
height: 492px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.box1-main {
margin-top: 17px;
margin-left: 22px;
width: 1556px;
height: 330px;
overflow-x: auto;
overflow-y: hidden;
display: flex;
position: relative;
.box1-line-box {
position: absolute;
left: 0;
top: 135px;
height: 8px;
width: 1556px;
background: url("./assets/icons/line-bg.png") repeat;
}
.box1-item {
width: 315px;
height: 142px;
position: relative;
box-sizing: border-box;
padding-left: 20px;
margin-left: 10px;
border-left: 1px solid #0a57a6;
.box1-item-header {
display: flex;
width: 315px;
.title {
// width: 262px;
height: 26px;
}
.icon {
margin-left: 10px;
margin-top: 5px;
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
}
.box1-item-content {
width: 288px;
min-height: 48px;
max-height: 96px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
.point {
position: absolute;
left: -11px;
bottom: -11px;
}
.pointFooter {
position: absolute;
left: -11px;
top: -11px;
}
.time {
height: 24px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
position: absolute;
bottom: -36px;
left: 0;
}
.timeFooter {
height: 24px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
position: absolute;
top: -36px;
left: 0;
}
}
.box1ItemFooter {
margin-top: 138px;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
}
.box1-footer {
margin-left: 22px;
margin-top: 10px;
width: 1556px;
height: 64px;
box-sizing: border-box;
padding: 6px 12px;
display: flex;
border: 1px solid rgba(231, 243, 255, 1);
border-radius: 4px;
background: rgba(246, 251, 255, 1);
display: flex;
.box1-footer-left {
width: 19px;
height: 20px;
margin-top: 16px;
img {
width: 100%;
height: 100%;
}
}
.box1-footer-center {
width: 1463px;
height: 48px;
display: flex;
flex-direction: row;
align-items: center;
margin-top: 2px;
margin-left: 15px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
.box1-footer-right {
width: 24px;
height: 24px;
border-radius: 12px;
background: #e7f3ff;
margin-top: 14px;
margin-left: 13px;
img {
margin-left: 6px;
margin-top: 6px;
width: 12px;
height: 12px;
}
}
}
}
.box2 {
margin: 16px auto; margin: 16px auto;
width: 1600px; width: 1600px;
height: 898px; height: 898px;
border-radius: 4px; border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2); box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
.box2-main { .box1-main {
display: flex; display: flex;
margin-top: 5px; margin-top: 5px;
.left { .left {
...@@ -676,7 +434,7 @@ const box2LeftActiveIndex = ref(0); ...@@ -676,7 +434,7 @@ const box2LeftActiveIndex = ref(0);
} }
} }
.list-footer { .list-footer {
margin-left: 35px; margin-left: 35px;
height: 32px; height: 32px;
margin-top: 10px; margin-top: 10px;
display: flex; display: flex;
......
<template> <template>
<div class="layout-container"> <div class="layout-container">
<!-- 导航菜单 --> <!-- 导航菜单 -->
<div class="layout-main"> <div class="layout-main">
<div class="layout-main-header"> <div class="layout-main-header">
<div class="layout-main-header-left-box"> <div class="layout-main-header-left-box">
<div class="left-box-top"> <div class="left-box-top">
<div class="icon"> <div class="icon">
<img src="./assets/images/USA-logo.png" alt="" /> <img src="./assets/images/USA-logo.png" alt="" />
</div> </div>
<div class="info"> <div class="info">
<div class="info-box1">{{ "EO 14320-推动美国人工智能技术栈的出口" }}</div> <div class="info-box1">{{ "EO 14320-推动美国人工智能技术栈的出口" }}</div>
<div class="info-box2"> <div class="info-box2">
<div class="info-box2-item">{{ '总统行动' }}</div>| <div class="info-box2-item">{{ "总统行动" }}</div>
<div class="info-box2-item">{{ '行政命令' }}</div>| |
<div class="info-box2-item">{{ 'Promoting the Export of the American AI Technology Stack' }}</div> <div class="info-box2-item">{{ "行政命令" }}</div>
</div> |
</div> <div class="info-box2-item">{{ "Promoting the Export of the American AI Technology Stack" }}</div>
</div> </div>
<div class="left-box-bottom"> </div>
<div </div>
class="left-box-bottom-item" <div class="left-box-bottom">
:class="{ leftBoxBottomItemActive: activeTitle === item.name }" <div
v-for="(item, index) in mainHeaderBtnList" class="left-box-bottom-item"
:key="index" :class="{ leftBoxBottomItemActive: activeTitle === item.name }"
@click="handleClickMainHeaderBtn(item)" v-for="(item, index) in mainHeaderBtnList"
> :key="index"
<div class="icon"> @click="handleClickMainHeaderBtn(item)"
<img v-if="activeTitle === item.name" :src="item.activeIcon" alt="" /> >
<img v-else :src="item.icon" alt="" /> <div class="icon">
</div> <img v-if="activeTitle === item.name" :src="item.activeIcon" alt="" />
<div class="name" :class="{ nameActive: activeTitle === item.name }"> <img v-else :src="item.icon" alt="" />
{{ item.name }} </div>
</div> <div class="name" :class="{ nameActive: activeTitle === item.name }">
</div> {{ item.name }}
</div> </div>
</div> </div>
<div class="layout-main-header-right-box"> </div>
<div class="right-box-top"> </div>
<div class="time">{{ "2025年7月23日" }}</div> <div class="layout-main-header-right-box">
<div class="name">{{ "唐纳德·约翰·特朗普(Donald John Trump)" }}</div> <div class="right-box-top">
</div> <div class="time">{{ "2025年7月23日" }}</div>
<div class="right-box-bottom"> <div class="name">{{ "唐纳德·约翰·特朗普(Donald John Trump)" }}</div>
<el-button </div>
type="plain" <div class="right-box-bottom">
size="large" <el-button type="plain" size="large" icon="Search" @click="handleSwitchActiveName('法案原文')"
icon="Search" >政令原文</el-button
@click="handleSwitchActiveName('法案原文')" >
>政令原文</el-button <el-button type="primary" size="large" icon="EditPen">分析报告</el-button>
> </div>
<el-button type="primary" size="large" icon="EditPen" </div>
>分析报告</el-button </div>
> <div class="layout-main-center">
</div> <router-view />
</div> </div>
</div> </div>
<div class="layout-main-center"> <div class="layout-report-box" v-if="activeName === '法案原文'">
<router-view /> <div class="report-close" @click="handleSwitchActiveName('分析报告')">
</div> <img src="./assets/images/report-close-icon.png" alt="" />
</div> </div>
<div class="layout-report-box" v-if="activeName === '法案原文'"> <div class="report-main">
<div class="report-close" @click="handleSwitchActiveName('分析报告')"> <div class="report-header">
<img src="./assets/images/report-close-icon.png" alt="" /> <div class="report-header-left">
</div> <div class="text">法案版本:</div>
<div class="report-main"> <div class="select-box">
<div class="report-header"> <el-select v-model="curBill" placeholder="选择法案" style="width: 240px">
<div class="report-header-left"> <el-option v-for="item in billList" :key="item.value" :label="item.label" :value="item.value" />
<div class="text">法案版本:</div> </el-select>
<div class="select-box"> </div>
<el-select </div>
v-model="curBill" <div class="report-header-right">
placeholder="选择法案" <div class="btn">
style="width: 240px" <div class="icon">
> <img src="./assets/images/report-header-icon1.png" alt="" />
<el-option </div>
v-for="item in billList" <div class="text">翻译</div>
:key="item.value" </div>
:label="item.label" <div class="btn">
:value="item.value" <div class="icon">
/> <img src="./assets/images/report-header-icon2.png" alt="" />
</el-select> </div>
</div> <div class="text">下载</div>
</div> </div>
<div class="report-header-right"> <div class="btn">
<div class="btn"> <div class="icon">
<div class="icon"> <img src="./assets/images/report-header-icon3.png" alt="" />
<img src="./assets/images/report-header-icon1.png" alt="" /> </div>
</div> <div class="text">对比</div>
<div class="text">翻译</div> </div>
</div> <div class="btn">
<div class="btn"> <div class="icon">
<div class="icon"> <img src="./assets/images/report-header-icon4.png" alt="" />
<img src="./assets/images/report-header-icon2.png" alt="" /> </div>
</div> <div class="text">查找</div>
<div class="text">下载</div> </div>
</div> </div>
<div class="btn"> </div>
<div class="icon"> <div class="report-content">
<img src="./assets/images/report-header-icon3.png" alt="" /> <div class="content-left">
</div> <img src="./assets/images/report1.png" alt="" />
<div class="text">对比</div> </div>
</div> <div class="content-right">
<div class="btn"> <img src="./assets/images/report2.png" alt="" />
<div class="icon"> </div>
<img src="./assets/images/report-header-icon4.png" alt="" /> </div>
</div> </div>
<div class="text">查找</div> </div>
</div> <!-- <div class="tool-box">
</div>
</div>
<div class="report-content">
<div class="content-left">
<img src="./assets/images/report1.png" alt="" />
</div>
<div class="content-right">
<img src="./assets/images/report2.png" alt="" />
</div>
</div>
</div>
</div>
<!-- <div class="tool-box">
<div class="tool1"> <div class="tool1">
<img src="./assets/icons/tool-icon1.png" alt="" /> <img src="./assets/icons/tool-icon1.png" alt="" />
</div> </div>
...@@ -129,29 +116,14 @@ ...@@ -129,29 +116,14 @@
<img src="./assets/icons/tool-icon3.png" alt="" /> <img src="./assets/icons/tool-icon3.png" alt="" />
</div> </div>
</div> --> </div> -->
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, onUnmounted } from "vue";
import router from "@/router"; import router from "@/router";
import GJKJAQImg from "./assets/images/icon1.png";
import GJKJAQActiveImg from "./assets/images/icon1.png";
import KJLYImg from "./assets/images/icon2.png";
import KJLYActiveImg from "./assets/images/icon2.png";
import KJYSImg from "./assets/images/icon3.png";
import KJYSActiveImg from "./assets/images/icon3.png";
import ZDKJAQImg from "./assets/images/icon4.png";
import ZDKJAQActiveImg from "./assets/images/icon4.png";
import ZBTXImg from "./assets/images/icon5.png";
import ZBTXActiveImg from "./assets/images/icon5.png";
import ZJKImg from "./assets/images/icon6.png";
import ZJKActiveImg from "./assets/images/icon6.png";
import XTGLImg from "./assets/images/icon7.png";
import XTGLActiveImg from "./assets/images/icon7.png";
import search from "./assets/images/search.png"; import search from "./assets/images/search.png";
import mail from "./assets/images/mail.png";
import icon1 from "./assets/icons/icon1.png"; import icon1 from "./assets/icons/icon1.png";
import icon1Active from "./assets/icons/icon1_active.png"; import icon1Active from "./assets/icons/icon1_active.png";
...@@ -159,508 +131,357 @@ import icon2 from "./assets/icons/icon2.png"; ...@@ -159,508 +131,357 @@ import icon2 from "./assets/icons/icon2.png";
import icon2Active from "./assets/icons/icon2_active.png"; import icon2Active from "./assets/icons/icon2_active.png";
import icon3 from "./assets/icons/icon3.png"; import icon3 from "./assets/icons/icon3.png";
import icon3Active from "./assets/icons/icon3_active.png"; import icon3Active from "./assets/icons/icon3_active.png";
import icon4 from "./assets/icons/icon4.png";
import icon4Active from "./assets/icons/icon4_active.png";
import headerIcon1 from "./assets/icons/header-icon1.png";
import headerIcon2 from "./assets/icons/header-icon2.png";
import headerIcon3 from "./assets/icons/header-icon3.png";
import headerIcon4 from "./assets/icons/header-icon4.png";
import headerIcon5 from "./assets/icons/header-icon5.png";
const activeName = ref("分析报告"); const activeName = ref("分析报告");
const handleSwitchActiveName = (name) => { const handleSwitchActiveName = name => {
activeName.value = name; activeName.value = name;
}; };
const curBill = ref("公法(2025年7月4日)"); const curBill = ref("公法(2025年7月4日)");
const billList = ref([ const billList = ref([
{ {
label: "公法(2025年7月4日)", label: "公法(2025年7月4日)",
value: "公法(2025年7月4日)", value: "公法(2025年7月4日)"
}, },
{ {
label: "公法(2025年7月2日)", label: "公法(2025年7月2日)",
value: "公法(2025年7月2日)", value: "公法(2025年7月2日)"
}, }
]); ]);
const mainHeaderBtnList = ref([ const mainHeaderBtnList = ref([
{ {
icon: icon1, icon: icon1,
activeIcon: icon1Active, activeIcon: icon1Active,
name: "政令概况", name: "政令概况",
path: "/decreeLayout/overview", path: "/decreeLayout/overview"
}, },
{ {
icon: icon2, icon: icon2,
activeIcon: icon2Active, activeIcon: icon2Active,
name: "深度挖掘", name: "深度挖掘",
path: "/decreeLayout/deepDig", path: "/decreeLayout/deepDig"
}, },
{ {
icon: icon3, icon: icon3,
activeIcon: icon3Active, activeIcon: icon3Active,
name: "影响分析", name: "影响分析",
path: "/decreeLayout/influence", path: "/decreeLayout/influence"
} }
]); ]);
const activeTitle = ref('法案概况') const activeTitle = ref("政令概况");
const handleClickMainHeaderBtn = (item) => {
activeTitle.value = item.name;
// window.sessionStorage.setItem('activeTitle', activeTitle.value)
router.push(item.path);
};
const activeNavIndex = ref(0);
const handleClickNav = (index, item) => { const handleClickMainHeaderBtn = item => {
activeNavIndex.value = index; activeTitle.value = item.name;
router.push(item.path); window.sessionStorage.setItem("activeTitle", item.name);
router.push(item.path);
}; };
onMounted(() => { onMounted(() => {
if(window.sessionStorage.getItem('activeTitle')) { if (window.sessionStorage.getItem("activeTitle")) {
activeTitle.value = window.sessionStorage.getItem('activeTitle') activeTitle.value = window.sessionStorage.getItem("activeTitle");
} }
});
onUnmounted(() => {
if (window.sessionStorage.getItem("activeTitle")) {
window.sessionStorage.removeItem("activeTitle");
}
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.layout-container { .layout-container {
width: 1920px; width: 1920px;
height: 1016px; height: 1016px;
background: rgba(249, 250, 252, 1); background: rgba(249, 250, 252, 1);
position: relative; position: relative;
// .layout-header { .layout-main {
// width: 1920px; width: 100%;
// height: 64px; height: 100%;
// // background: #0a121e; .layout-main-header {
// background: #fff; height: 137px;
// // border-bottom: 1px solid rgba(0, 0, 0, 0.1); background: rgba(255, 255, 255, 1);
// box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1); display: flex;
// // margin-bottom: 13px; justify-content: space-between;
// display: flex; .layout-main-header-left-box {
// position: relative; width: 800px;
// z-index: 99; margin-left: 160px;
// .layout-header-left { margin-top: 13px;
// width: 480px; .left-box-top {
// display: flex; height: 64px;
// .logo-box { display: flex;
// width: 36px; .icon {
// height: 36px; width: 64px;
// margin: 14px; height: 64px;
}
// img { .info {
// width: 100%; margin-left: 9px;
// height: 100%; .info-box1 {
// border-radius: 6px; color: rgba(59, 65, 75, 1);
// } font-family: Microsoft YaHei;
// } font-size: 20px;
// .title-box { font-weight: 600;
// height: 64px; line-height: 22px;
// width: 350px; letter-spacing: 0px;
// margin: 0 5px; text-align: left;
// color: #eee; margin-top: 5px;
// line-height: 64px; }
// font-size: 20px; .info-box2 {
// font-weight: bold; margin-top: 5px;
// color: rgba(10, 18, 30, 1); height: 22px;
// font-family: Microsoft YaHei; line-height: 22px;
// font-size: 22px; color: rgba(132, 136, 142, 1);
// font-weight: 700; font-family: Microsoft YaHei;
// text-align: left; font-size: 14px;
// } font-weight: 400;
// } line-height: 22px;
// .layout-header-center { letter-spacing: 0px;
// width: 700px; text-align: left;
// display: flex; display: flex;
// justify-content: space-between; margin-left: -10px;
// margin-left: 200px; .info-box2-item {
// .nav-item { padding: 0 10px;
// border-radius: 5px; }
// cursor: pointer; }
// display: flex; }
// &:hover { }
// background: rgba(255, 255, 255, 0.2); .left-box-bottom {
// } display: flex;
// .nav-icon-box { height: 40px;
// width: 25px; margin-top: 21px;
// height: 25px; .left-box-bottom-item {
// margin: 22px 0 20px 5px; display: flex;
// .nav-icon { margin-right: 32px;
// width: 20px; margin-top: 3px;
// height: 20px; height: 35px;
// img { cursor: pointer;
// width: 100%; .icon {
// height: 100%; margin-top: 4px;
// } width: 16px;
// } height: 16px;
// .nav-icon-active { img {
// width: 20px; width: 100%;
// height: 20px; height: 100%;
// img { }
// width: 100%; }
// height: 100%; .name {
// } height: 24px;
// } color: rgba(59, 65, 75, 1);
// } font-family: Microsoft YaHei;
// .name-box { font-size: 18px;
// margin: 18px 5px; font-weight: 400;
// height: 30px; line-height: 24px;
// text-align: center; letter-spacing: 0px;
// line-height: 30px; text-align: left;
// color: rgba(59, 65, 75, 1); margin-left: 3px;
// letter-spacing: 2px; }
// font-size: 18px; .nameActive {
// } color: var(--color-main-active);
// // .nameActive { font-weight: 700;
// // color: #ea9518; }
// // font-weight: bold; }
// // } .leftBoxBottomItemActive {
// } border-bottom: 3px solid var(--color-main-active);
// .navItemActive { }
// // background: #295dab; }
// // border-bottom: 4px solid #ea9518; }
// // &:hover { .layout-main-header-right-box {
// // background: #295dab; width: 300px;
// // border-bottom: 4px solid #ea9518; margin-right: 150px;
// // } margin-top: 19px;
// } .right-box-top {
// } .time {
// .layout-header-right { height: 24px;
// flex: 1; line-height: 24px;
// display: flex; color: rgba(95, 101, 108, 1);
// justify-content: flex-end; font-family: Microsoft YaHei;
font-size: 16px;
// .nav-search { font-weight: 400;
// width: 22px; line-height: 22px;
// height: 22px; letter-spacing: 0px;
// margin: 21px 0; text-align: right;
// } }
.name {
// .nav-message { height: 24px;
// width: 22px; line-height: 24px;
// height: 22px; color: rgba(95, 101, 108, 1);
// margin: 21px 30px; font-family: Microsoft YaHei;
// } font-size: 16px;
font-weight: 400;
// .nav-usr { line-height: 22px;
// width: 110px; letter-spacing: 0px;
// display: flex; text-align: right;
// height: 40px; }
// margin: 12px 5px 12px 0; }
// .usr-img { .right-box-bottom {
// margin-top: 4px; margin-top: 24px;
// height: 32px; text-align: right;
// width: 32px; }
// background: rgba(255, 255, 255, 0.5); }
// border-radius: 100%; }
// box-sizing: border-box; .layout-main-center {
// padding: 4px; // height: calc(100% - 137px);
// // img { overflow: hidden;
// // width: 100%; }
// // height: 100%; }
// // } .layout-report-box {
// } position: absolute;
// .usr-info { z-index: 9999;
// height: 40px; top: 154px;
// line-height: 40px; left: 0;
// text-align: center; width: 100%;
// font-size: 14px; height: 926px;
// margin-left: 10px; background: rgba(248, 249, 250, 1);
// } .report-close {
// } position: absolute;
// } top: 24px;
// } right: 178px;
.layout-main { width: 32px;
width: 100%; height: 32px;
height: 100%; cursor: pointer;
.layout-main-header { img {
height: 137px; width: 100%;
background: rgba(255, 255, 255, 1); height: 100%;
display: flex; }
justify-content: space-between; }
.layout-main-header-left-box { .report-main {
width: 800px; width: 1600px;
margin-left: 160px; height: 926px;
margin-top: 13px; margin: 0 auto;
.left-box-top { background: #fff;
height: 64px; box-sizing: border-box;
display: flex; padding: 0 69px;
.icon { .report-header {
width: 64px; height: 77px;
height: 64px; border-bottom: 1px solid rgba(240, 242, 244, 1);
} display: flex;
.info { justify-content: space-between;
margin-left: 9px; .report-header-left {
.info-box1 { display: flex;
color: rgba(59, 65, 75, 1); .text {
font-family: Microsoft YaHei; margin-top: 32px;
font-size: 20px; width: 70px;
font-weight: 600; height: 14px;
line-height: 22px; color: rgba(95, 101, 108, 1);
letter-spacing: 0px; font-family: Microsoft YaHei;
text-align: left; font-size: 14px;
margin-top: 5px; font-weight: 400;
} line-height: 14px;
.info-box2 { }
margin-top: 5px; .select-box {
height: 22px; margin-left: 8px;
line-height: 22px; margin-top: 23px;
color: rgba(132, 136, 142, 1); }
font-family: Microsoft YaHei; }
font-size: 14px; .report-header-right {
font-weight: 400; display: flex;
line-height: 22px; margin-top: 24px;
letter-spacing: 0px; .btn {
text-align: left; display: flex;
display: flex; width: 88px;
margin-left: -10px; height: 32px;
.info-box2-item{ margin-left: 8px;
padding: 0 10px; box-sizing: border-box;
} border: 1px solid rgba(230, 231, 232, 1);
} border-radius: 4px;
} background: rgba(255, 255, 255, 1);
} display: flex;
.left-box-bottom { justify-content: center;
display: flex; align-items: center;
height: 40px; .icon {
margin-top: 21px; width: 16px;
.left-box-bottom-item { height: 16px;
display: flex; img {
margin-right: 32px; width: 100%;
margin-top: 3px; height: 100%;
height: 35px; }
cursor: pointer; }
.icon { .text {
margin-top: 4px; margin-left: 8px;
width: 16px; height: 32px;
height: 16px; color: rgba(95, 101, 108, 1);
img { font-family: Microsoft YaHei;
width: 100%; font-size: 16px;
height: 100%; font-weight: 400;
} line-height: 32px;
} }
.name { }
height: 24px; }
color: rgba(59, 65, 75, 1); }
font-family: Microsoft YaHei; .report-content {
font-size: 18px; display: flex;
font-weight: 400; margin-top: 35px;
line-height: 24px; .content-left {
letter-spacing: 0px; width: 680px;
text-align: left; height: 786px;
margin-left: 3px; // background: #eee;
} // overflow-y: auto;
.nameActive { img {
color: var(--color-main-active); width: 100%;
font-weight: 700; height: 100%;
} }
} }
.leftBoxBottomItemActive { .content-right {
border-bottom: 3px solid var(--color-main-active); margin-left: 89px;
} width: 680px;
} height: 786px;
} // background: #eee;
.layout-main-header-right-box { // overflow-y: auto;
width: 300px; img {
margin-right: 150px; width: 100%;
margin-top: 19px; height: 100%;
.right-box-top { }
.time { }
height: 24px; }
line-height: 24px; }
color: rgba(95, 101, 108, 1); }
font-family: Microsoft YaHei; // .tool-box {
font-size: 16px; // position: fixed;
font-weight: 400; // z-index: 10000;
line-height: 22px; // bottom: 80px;
letter-spacing: 0px; // left: 0;
text-align: right; // width: 48px;
} // height: 144px;
.name { // border-radius: 0px 10px 10px 0px;
height: 24px; // box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
line-height: 24px; // background: rgba(255, 255, 255, 1);
color: rgba(95, 101, 108, 1); // .tool1 {
font-family: Microsoft YaHei; // width: 17px;
font-size: 16px; // height: 18px;
font-weight: 400; // margin-top: 17px;
line-height: 22px; // margin-left: 16px;
letter-spacing: 0px; // cursor: pointer;
text-align: right; // img {
} // width: 100%;
} // height: 100%;
.right-box-bottom { // }
margin-top: 24px; // }
text-align: right; // .tool2 {
} // width: 22px;
} // height: 20px;
} // margin-top: 26px;
.layout-main-center { // margin-left: 14px;
height: calc(100% - 137px); // cursor: pointer;
overflow-y: auto; // img {
overflow-x: hidden; // width: 100%;
} // height: 100%;
} // }
.layout-report-box { // }
position: absolute; // .tool3 {
z-index: 9999; // width: 20px;
top: 154px; // height: 20px;
left: 0; // margin-top: 25px;
width: 100%; // margin-left: 15px;
height: 926px; // cursor: pointer;
background: rgba(248, 249, 250, 1); // img {
.report-close { // width: 100%;
position: absolute; // height: 100%;
top: 24px; // }
right: 178px; // }
width: 32px; // }
height: 32px;
cursor: pointer;
img {
width: 100%;
height: 100%;
}
}
.report-main {
width: 1600px;
height: 926px;
margin: 0 auto;
background: #fff;
box-sizing: border-box;
padding: 0 69px;
.report-header {
height: 77px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex;
justify-content: space-between;
.report-header-left {
display: flex;
.text {
margin-top: 32px;
width: 70px;
height: 14px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 14px;
}
.select-box {
margin-left: 8px;
margin-top: 23px;
}
}
.report-header-right {
display: flex;
margin-top: 24px;
.btn {
display: flex;
width: 88px;
height: 32px;
margin-left: 8px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
display: flex;
justify-content: center;
align-items: center;
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
margin-left: 8px;
height: 32px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 32px;
}
}
}
}
.report-content {
display: flex;
margin-top: 35px;
.content-left {
width: 680px;
height: 786px;
// background: #eee;
// overflow-y: auto;
img {
width: 100%;
height: 100%;
}
}
.content-right {
margin-left: 89px;
width: 680px;
height: 786px;
// background: #eee;
// overflow-y: auto;
img {
width: 100%;
height: 100%;
}
}
}
}
}
// .tool-box {
// position: fixed;
// z-index: 10000;
// bottom: 80px;
// left: 0;
// width: 48px;
// height: 144px;
// border-radius: 0px 10px 10px 0px;
// box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
// background: rgba(255, 255, 255, 1);
// .tool1 {
// width: 17px;
// height: 18px;
// margin-top: 17px;
// margin-left: 16px;
// cursor: pointer;
// img {
// width: 100%;
// height: 100%;
// }
// }
// .tool2 {
// width: 22px;
// height: 20px;
// margin-top: 26px;
// margin-left: 14px;
// cursor: pointer;
// img {
// width: 100%;
// height: 100%;
// }
// }
// .tool3 {
// width: 20px;
// height: 20px;
// margin-top: 25px;
// margin-left: 15px;
// cursor: pointer;
// img {
// width: 100%;
// height: 100%;
// }
// }
// }
} }
</style> </style>
\ No newline at end of file
...@@ -25,9 +25,10 @@ ...@@ -25,9 +25,10 @@
<div class="box1-tab-box"> <div class="box1-tab-box">
<div <div
class="tab" class="tab"
:class="{ tabActive: tabActiveIndex === index }" :class="{ tabActive: box1BtnActiveName === item }"
v-for="(item, index) in tabList" v-for="(item, index) in box1BtnList"
:key="index" :key="index"
@click="handleClickBox1Btn(item)"
> >
{{ item }} {{ item }}
</div> </div>
...@@ -51,7 +52,7 @@ ...@@ -51,7 +52,7 @@
</div> </div>
</div> </div>
<div class="box1-footer"> <div class="box1-footer">
<div class="box1-footer-left">{{ `共105家企业` }}</div> <div class="box1-footer-left">{{ `共${companyTotalNum}家企业` }}</div>
<div class="box1-footer-right"> <div class="box1-footer-right">
<el-pagination <el-pagination
background background
...@@ -100,7 +101,7 @@ ...@@ -100,7 +101,7 @@
</div> </div>
<div class="box2-footer"> <div class="box2-footer">
<div class="footer-left"> <div class="footer-left">
<img src="./assets/images/footer-icon1.png" alt="" /> <img src="@/assets/icons/box-footer-left-icon.png" alt="" />
</div> </div>
<div class="footer-center"> <div class="footer-center">
{{ {{
...@@ -108,7 +109,7 @@ ...@@ -108,7 +109,7 @@
}} }}
</div> </div>
<div class="footer-right"> <div class="footer-right">
<img src="./assets/images/footer-icon2.png" alt="" /> <img src="@/assets/icons/box-footer-right-icon.png" alt="" />
</div> </div>
</div> </div>
</div> </div>
...@@ -147,7 +148,7 @@ ...@@ -147,7 +148,7 @@
</div> </div>
<div class="box3-footer"> <div class="box3-footer">
<div class="footer-left"> <div class="footer-left">
<img src="./assets/images/footer-icon1.png" alt="" /> <img src="@/assets/icons/box-footer-left-icon.png" alt="" />
</div> </div>
<div class="footer-center"> <div class="footer-center">
{{ {{
...@@ -155,7 +156,7 @@ ...@@ -155,7 +156,7 @@
}} }}
</div> </div>
<div class="footer-right"> <div class="footer-right">
<img src="./assets/images/footer-icon2.png" alt="" /> <img src="@/assets/icons/box-footer-right-icon.png" alt="" />
</div> </div>
</div> </div>
</div> </div>
...@@ -165,17 +166,21 @@ ...@@ -165,17 +166,21 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import setChart from "@/utils/setChart";
import * as echarts from "echarts"; import * as echarts from "echarts";
import getBarChart from "./utils/barChart"; import getBarChart from "./utils/barChart";
// 企业影响分析
const chart1Data = ref({ const chart1Data = ref({
title: ["集成电路", "新能源", "人工智能", "先进制造", "量子科技"], title: ["集成电路", "新能源", "人工智能", "先进制造", "量子科技"],
value: [109, 95, 79, 25, 11], value: [109, 95, 79, 25, 11],
}); });
const box1BtnActiveName = ref('集成电路');
const tabActiveIndex = ref(0); const box1BtnList = ref(["集成电路", "新能源", "人工智能", "先进制造", "量子科技"]);
const tabList = ref(["集成电路", "新能源", "人工智能", "先进制造", "量子科技"]); const handleClickBox1Btn = btn => {
box1BtnActiveName.value = btn
}
const companyList = ref([ const companyList = ref([
{ {
name: "宁德时代新能源科技股份有限公司", name: "宁德时代新能源科技股份有限公司",
...@@ -218,11 +223,36 @@ const companyList = ref([ ...@@ -218,11 +223,36 @@ const companyList = ref([
status: "up", status: "up",
}, },
]); ]);
const companyTotalNum = ref(105); // 企业数量
const isChecked = ref(true); // 只看中国企业
const companyTotalNum = ref(105);
const isChecked = ref(true); // 政令举措落实情况
const timeLineList = ref([
{
time: "2025年7月25日",
content: "商务部已成立AI出口计划办公室,并开始招募专业人员。",
},
{
time: "2025年7月31日",
content: "英伟达、微软、谷歌等企业已提交初步技术栈提案。",
},
{
time: "2025年8月5日",
content: "国务院开始与盟友国家进行初步磋商。",
},
{
time: "2025年8月9日",
content:"国防部、能源部安全审查流程尚未最终确定。",
},
{
time: "2025年8月12日",
content: "商务部已成立AI出口计划办公室,并开始招募专业人员。",
},
]);
// 历史相似举措及落实情况
const box3List = ref([ const box3List = ref([
{ {
type: "科技法案", type: "科技法案",
...@@ -268,38 +298,6 @@ const box3List = ref([ ...@@ -268,38 +298,6 @@ const box3List = ref([
}, },
]); ]);
const timeLineList = ref([
{
time: "2025年7月25日",
content: "商务部已成立AI出口计划办公室,并开始招募专业人员。",
},
{
time: "2025年7月31日",
content: "英伟达、微软、谷歌等企业已提交初步技术栈提案。",
},
{
time: "2025年8月5日",
content: "国务院开始与盟友国家进行初步磋商。",
},
{
time: "2025年8月9日",
content:"国防部、能源部安全审查流程尚未最终确定。",
},
{
time: "2025年8月12日",
content: "商务部已成立AI出口计划办公室,并开始招募专业人员。",
},
]);
// 绘制echarts图表
const setChart = (option, chartId) => {
let chartDom = document.getElementById(chartId);
chartDom.removeAttribute("_echarts_instance_");
let chart = echarts.init(chartDom);
chart.setOption(option);
return chart;
};
onMounted(() => { onMounted(() => {
let chart1 = getBarChart(chart1Data.value.title, chart1Data.value.value); let chart1 = getBarChart(chart1Data.value.title, chart1Data.value.value);
setChart(chart1, "chart1"); setChart(chart1, "chart1");
...@@ -492,13 +490,12 @@ onMounted(() => { ...@@ -492,13 +490,12 @@ onMounted(() => {
left: 0; left: 0;
top: 114px; top: 114px;
height: 8px; height: 8px;
width: 1556px; width: 1054px;
background: url("./assets/images/line-bg.png") repeat; background: url("./assets/images/line-bg.png") repeat;
} }
.box2-item { .box2-item {
width: 300px; width: 300px;
height: 120px; height: 120px;
// background: pink;
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
padding-left: 13px; padding-left: 13px;
...@@ -607,12 +604,10 @@ onMounted(() => { ...@@ -607,12 +604,10 @@ onMounted(() => {
width: 24px; width: 24px;
height: 24px; height: 24px;
border-radius: 12px; border-radius: 12px;
background: rgba(231, 243, 255, 1);
margin-top: 14px; margin-top: 14px;
img { img {
margin: 6px; width: 100%;
width: 12px; height: 100%;
height: 12px;
} }
} }
} }
...@@ -753,12 +748,10 @@ onMounted(() => { ...@@ -753,12 +748,10 @@ onMounted(() => {
width: 24px; width: 24px;
height: 24px; height: 24px;
border-radius: 12px; border-radius: 12px;
background: rgba(231, 243, 255, 1);
margin-top: 14px; margin-top: 14px;
img { img {
margin: 6px; width: 100%;
width: 12px; height: 100%;
height: 12px;
} }
} }
} }
......
...@@ -6,13 +6,14 @@ ...@@ -6,13 +6,14 @@
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">提出背景</div> <div class="title">提出背景</div>
<div class="header-btn-box"> <div class="header-btn-box">
<div class="btn" @click="handleClickBox1Btn(1)"> <div
<el-button type="primary" plain v-if="box1BtnActive === 1">涉华背景</el-button> class="btn"
<el-button type="info" plain v-else>涉华背景</el-button> :class="{ btnActive: box1ActiveBtn === item }"
</div> v-for="(item, index) in box1BtnList"
<div class="btn" @click="handleClickBox1Btn(2)"> :key="index"
<el-button type="primary" plain v-if="box1BtnActive === 2">全部背景</el-button> @click="handleClickBox1Btn(item)"
<el-button type="info" plain v-else>全部背景</el-button> >
{{ item }}
</div> </div>
</div> </div>
<div class="header-right"> <div class="header-right">
...@@ -109,8 +110,12 @@ import Img3 from "./assets/images/box2-img3.png"; ...@@ -109,8 +110,12 @@ import Img3 from "./assets/images/box2-img3.png";
import Img4 from "./assets/images/box2-img4.png"; import Img4 from "./assets/images/box2-img4.png";
import Img5 from "./assets/images/box2-img5.png"; import Img5 from "./assets/images/box2-img5.png";
const box1BtnActive = ref(1); // 提出背景
const box1BtnList = ref(["涉华背景", "全部背景"]);
const box1ActiveBtn = ref("涉华背景");
const handleClickBox1Btn = btn => {
box1ActiveBtn.value = btn;
};
const backgroundList = ref([ const backgroundList = ref([
{ {
title: "认为人工智能(AI)是一项将决定未来几十年经济增长、国家安全和全球竞争力的基础性技术" title: "认为人工智能(AI)是一项将决定未来几十年经济增长、国家安全和全球竞争力的基础性技术"
...@@ -129,6 +134,7 @@ const backgroundList = ref([ ...@@ -129,6 +134,7 @@ const backgroundList = ref([
} }
]); ]);
// 相关事件
const relatedEvents = ref([ const relatedEvents = ref([
{ {
image: Img1, image: Img1,
...@@ -165,6 +171,8 @@ const relatedEvents = ref([ ...@@ -165,6 +171,8 @@ const relatedEvents = ref([
} }
]); ]);
// 法律依据
const laws = ref([ const laws = ref([
{ {
name: "《美国法典》", name: "《美国法典》",
...@@ -226,8 +234,26 @@ const laws = ref([ ...@@ -226,8 +234,26 @@ const laws = ref([
top: 14px; top: 14px;
right: 84px; right: 84px;
display: flex; display: flex;
justify-content: flex-end;
gap: 8px;
.btn { .btn {
margin-left: 8px; height: 28px;
padding: 0 8px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 28px;
cursor: pointer;
}
.btnActive {
border: 1px solid var(--color-main-active);
color: var(--color-main-active);
background: rgba(231, 243, 255, 1);
} }
} }
.header-right { .header-right {
...@@ -347,12 +373,16 @@ const laws = ref([ ...@@ -347,12 +373,16 @@ const laws = ref([
margin-top: -5px; margin-top: -5px;
} }
.content { .content {
width: 892px;
height: 30px; height: 30px;
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 16px; font-size: 16px;
font-weight: 400; font-weight: 400;
line-height: 30px; line-height: 30px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
} }
.item-right { .item-right {
......
<template> <template>
<div class="decree-overview-wrap"> <div class="decree-overview-wrap">
<div class="left"> <div class="left">
<div <div
class="sider-btn" class="sider-btn"
:class="{ siderBtnActive: siderBtnActive === item.name }" :class="{ siderBtnActive: siderBtnActive === item.name }"
@click="handleClickLeftSiderBtn(item)" @click="handleClickLeftSiderBtn(item)"
v-for="(item, index) in siderList" v-for="(item, index) in siderList"
:key="index" :key="index"
> >
<div class="btn-text">{{ item.name }}</div> <div class="btn-text">{{ item.name }}</div>
<div class="btn-icon"> <div class="btn-icon">
<el-icon v-if="siderBtnActive === item.name" color="#fff" <el-icon v-if="siderBtnActive === item.name" color="#fff"><CaretRight /></el-icon>
><CaretRight </div>
/></el-icon> </div>
</div> </div>
</div> <div class="main">
</div> <router-view />
<div class="main"> </div>
<router-view /> </div>
</div>
</div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted, onUnmounted } from "vue";
import router from '@/router' import router from "@/router";
const siderList = ref([ const siderList = ref([
{ {
name: "政令简介", name: "政令简介",
path: "/decreeLayout/overview/introduction", path: "/decreeLayout/overview/introduction"
}, },
{ {
name: "政令背景", name: "政令背景",
path: "/decreeLayout/overview/background", path: "/decreeLayout/overview/background"
}, }
]); ]);
const siderBtnActive = ref("政令简介"); const siderBtnActive = ref("政令简介");
const handleClickLeftSiderBtn = (item) => { const handleClickLeftSiderBtn = item => {
siderBtnActive.value = item.name window.sessionStorage.setItem("siderBarActiveName", item.name);
router.push(item.path) siderBtnActive.value = item.name;
} router.push(item.path);
};
onMounted(() => {
if (window.sessionStorage.getItem("siderBarActiveName")) {
siderBtnActive.value = window.sessionStorage.getItem("siderBarActiveName");
}
});
onUnmounted(() => {
if (window.sessionStorage.getItem("siderBarActiveName")) {
window.sessionStorage.removeItem("siderBarActiveName");
}
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.decree-overview-wrap { .decree-overview-wrap {
width: 1920px; width: 1920px;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
background: rgba(247, 248, 249, 1); background: rgba(247, 248, 249, 1);
display: flex; display: flex;
.left { .left {
width: 160px; width: 160px;
padding-top: 16px; padding-top: 16px;
.sider-btn { .sider-btn {
margin-top: 20px; margin-top: 20px;
margin-left: 20px; margin-left: 20px;
width: 120px; width: 120px;
height: 32px; height: 32px;
display: flex; display: flex;
border-radius: 16px; border-radius: 16px;
cursor: pointer; cursor: pointer;
.btn-text { .btn-text {
margin-left: 28px; margin-left: 28px;
width: 68px; width: 68px;
height: 32px; height: 32px;
line-height: 32px; line-height: 32px;
text-align: left; text-align: left;
box-sizing: border-box; box-sizing: border-box;
font-size: 16px; font-size: 16px;
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
color: rgba(95, 101, 108, 1); color: rgba(95, 101, 108, 1);
} }
.btn-icon { .btn-icon {
width: 22px; width: 22px;
padding-top: 9px; padding-top: 9px;
} }
} }
.siderBtnActive { .siderBtnActive {
background: var(--color-main-active); background: var(--color-main-active);
.btn-text { .btn-text {
color: #fff !important; color: #fff !important;
} }
} }
} }
.main{ .main {
width: 1760px; width: 1760px;
height: 901px; height: 901px;
} }
} }
</style> </style>
\ No newline at end of file
...@@ -22,42 +22,42 @@ ...@@ -22,42 +22,42 @@
<div class="box1-main-right"> <div class="box1-main-right">
<div class="item"> <div class="item">
<div class="item-left">{{ "政令全称:" }}</div> <div class="item-left">{{ "政令全称:" }}</div>
<div class="item-right">{{ "推动美国人工智能技术栈出口" }}</div> <div class="item-right">{{ basicInfo.name }}</div>
</div> </div>
<div class="item"> <div class="item">
<div class="item-left">{{ "英文全称:" }}</div> <div class="item-left">{{ "英文全称:" }}</div>
<div class="item-right text"> <div class="item-right text">
{{ "Promoting the Export of the American AI Technology Stack" }} {{ basicInfo.eName }}
</div> </div>
</div> </div>
<div class="item"> <div class="item">
<div class="item-left">{{ "相关领域:" }}</div> <div class="item-left">{{ "相关领域:" }}</div>
<div class="item-right tag-box"> <div class="item-right tag-box">
<div class="tag" v-for="(area, index) in areaList" :key="index"> <div class="tag" v-for="(area, index) in basicInfo.areaList" :key="index">
{{ area }} {{ area }}
</div> </div>
</div> </div>
</div> </div>
<div class="item"> <div class="item">
<div class="item-left">{{ "签署时间:" }}</div> <div class="item-left">{{ "签署时间:" }}</div>
<div class="item-right text">{{ "2025年7月23日" }}</div> <div class="item-right text">{{ basicInfo.signTime }}</div>
</div> </div>
<div class="item"> <div class="item">
<div class="item-left">{{ "签署总统:" }}</div> <div class="item-left">{{ "签署总统:" }}</div>
<div class="item-right text"> <div class="item-right text">
{{ "唐纳德·约翰·特朗普(Donald John Trump)" }} {{ basicInfo.signPeople }}
</div> </div>
</div> </div>
<div class="item"> <div class="item">
<div class="item-left">{{ "政令编号:" }}</div> <div class="item-left">{{ "政令编号:" }}</div>
<div class="item-right text"> <div class="item-right text">
{{ "第14320号行政命令 (EO 14320)" }} {{ basicInfo.bh }}
</div> </div>
</div> </div>
<div class="item"> <div class="item">
<div class="item-left">{{ "执行期限:" }}</div> <div class="item-left">{{ "执行期限:" }}</div>
<div class="item-right text"> <div class="item-right text">
{{ "签署后90天内建立机制并开始实施" }} {{ basicInfo.deadline }}
</div> </div>
</div> </div>
</div> </div>
...@@ -99,13 +99,14 @@ ...@@ -99,13 +99,14 @@
<div class="header-left"></div> <div class="header-left"></div>
<div class="title">执行机构</div> <div class="title">执行机构</div>
<div class="header-btn-box"> <div class="header-btn-box">
<div class="btn" @click="handleClickBox1Btn(1)"> <div
<el-button type="primary" plain v-if="box1BtnActive === 1">商务部</el-button> class="btn"
<el-button type="info" plain v-else>商务部</el-button> :class="{ btnActive: box3ActiveBtn === item }"
</div> v-for="(item, index) in box3BtnList"
<div class="btn" @click="handleClickBox1Btn(2)"> :key="index"
<el-button type="primary" plain v-if="box1BtnActive === 2">经济外交行动组</el-button> @click="handleClickBox3Btn(item)"
<el-button type="info" plain v-else>经济外交行动组</el-button> >
{{ item }}
</div> </div>
</div> </div>
<div class="header-right"> <div class="header-right">
...@@ -120,11 +121,11 @@ ...@@ -120,11 +121,11 @@
<div class="box3-top"> <div class="box3-top">
<div class="box3-top-top"> <div class="box3-top-top">
<div class="left"> <div class="left">
<img src="./assets/images/box3-img.png" alt="" /> <img :src="box3TopData.logo" alt="" />
</div> </div>
<div class="right"> <div class="right">
<div class="name">{{ "美国商务部" }}</div> <div class="name">{{ box3TopData.name }}</div>
<div class="ename">{{ "United States Department of Commerce" }}</div> <div class="ename">{{ box3TopData.eName }}</div>
</div> </div>
<!-- <div class="more"> <!-- <div class="more">
<div class="text">{{ "查看官网" }}</div> <div class="text">{{ "查看官网" }}</div>
...@@ -138,26 +139,26 @@ ...@@ -138,26 +139,26 @@
<div class="main-item"> <div class="main-item">
<div class="item-icon"></div> <div class="item-icon"></div>
<div class="item-left">{{ "成立时间:" }}</div> <div class="item-left">{{ "成立时间:" }}</div>
<div class="item-right">{{ "1903年2月14日" }}</div> <div class="item-right">{{ box3TopData.clsj }}</div>
</div> </div>
<div class="main-item"> <div class="main-item">
<div class="item-icon"></div> <div class="item-icon"></div>
<div class="item-left">{{ "主要职责:" }}</div> <div class="item-left">{{ "主要职责:" }}</div>
<div class="item-right"> <div class="item-right">
{{ "国际贸易、进出口管制(R-TX-19)" }} {{ box3TopData.zyzz }}
</div> </div>
</div> </div>
<div class="main-item"> <div class="main-item">
<div class="item-icon"></div> <div class="item-icon"></div>
<div class="item-left">{{ "总部地址:" }}</div> <div class="item-left">{{ "总部地址:" }}</div>
<div class="item-right"> <div class="item-right">
{{ "华盛顿宪法大道1401号胡佛大楼" }} {{ box3TopData.zbdz }}
</div> </div>
</div> </div>
<div class="main-item"> <div class="main-item">
<div class="item-icon"></div> <div class="item-icon"></div>
<div class="item-left">{{ "部长:" }}</div> <div class="item-left">{{ "部长:" }}</div>
<div class="item-right">{{ "霍华德·卢特尼克" }}</div> <div class="item-right">{{ box3TopData.bz }}</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -194,10 +195,21 @@ ...@@ -194,10 +195,21 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
const box1BtnActive = ref(1);
const areaList = ref(["人工智能", "出口管制", "半导体产业", "关税", "光伏产业"]); import Box3Logo from "./assets/images/box3-img.png";
// 基本信息
const basicInfo = ref({
name: "推动美国人工智能技术栈出口",
eName: "Promoting the Export of the American AI Technology Stack",
areaList: ["人工智能", "出口管制", "半导体产业", "关税", "光伏产业"],
signTime: "2025年7月23日",
signPeople: "唐纳德·约翰·特朗普(Donald John Trump)",
bh: "第14320号行政命令 (EO 14320)",
deadline: "签署后90天内建立机制并开始实施"
});
// 主要指令
const majorList = ref([ const majorList = ref([
{ {
title: '要求商务部在90天内建立"全栈式"美国AI出口机制。' title: '要求商务部在90天内建立"全栈式"美国AI出口机制。'
...@@ -216,7 +228,24 @@ const majorList = ref([ ...@@ -216,7 +228,24 @@ const majorList = ref([
} }
]); ]);
// 人物动态 // 执行机构
const box3BtnList = ref(["商务部", "经济外交行动组"]);
const box3ActiveBtn = ref("商务部");
const handleClickBox3Btn = btn => {
box3ActiveBtn.value = btn;
};
const box3TopData = ref({
logo: Box3Logo,
name: "美国商务部",
eName: "United States Department of Commerce",
clsj: "1903年2月14日",
zyzz: "国际贸易、进出口管制(R-TX-19)",
zbdz: "华盛顿宪法大道1401号胡佛大楼",
bz: "霍华德·卢特尼克"
});
// 机构动态
const eventList = ref([ const eventList = ref([
{ {
time: "2025-07-31", time: "2025-07-31",
...@@ -269,8 +298,26 @@ const eventList = ref([ ...@@ -269,8 +298,26 @@ const eventList = ref([
top: 14px; top: 14px;
right: 84px; right: 84px;
display: flex; display: flex;
justify-content: flex-end;
gap: 8px;
.btn { .btn {
margin-left: 8px; height: 28px;
padding: 0 8px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 28px;
cursor: pointer;
}
.btnActive {
border: 1px solid var(--color-main-active);
color: var(--color-main-active);
background: rgba(231, 243, 255, 1);
} }
} }
.header-right { .header-right {
...@@ -327,6 +374,8 @@ const eventList = ref([ ...@@ -327,6 +374,8 @@ const eventList = ref([
.tag-box { .tag-box {
display: flex; display: flex;
.tag { .tag {
height: 24px;
line-height: 24px;
color: rgba(22, 119, 255, 1); color: rgba(22, 119, 255, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 14px; font-size: 14px;
......
<template>
<div class="sanction-container">
<!-- 页面标题区域 -->
<div class="page-header">
<!-- <h1 class="main-title">制裁分析</h1> -->
<img class="page-header-img" src="@/assets/images/decree-national.png" alt="" />
<div class="bill-details">
<div class="main-title">EO 14320-促进美国人工智能技术栈的出口</div>
<div class="bill-name-en">总统行动 | 行政命令 | Ending Crime and Disorder on America’s Streets</div>
</div>
<div class="date-author">
<div class="date">2025年7月23日</div>
<div class="author">唐纳德·约翰·特朗普(Donald John Trump))</div>
</div>
<!-- <div class="bill-info">
</div> -->
</div>
<!-- 导航标签区域 -->
<!-- <div class="nav-section">
<div class="tabs">
<div class="tab-item active">制裁概况</div>
<div class="tab-item">深度挖掘</div>
<div class="tab-item">影响分析</div>
</div>
<div class="action-buttons">
<el-button>法案原文</el-button>
<el-button type="primary">分析报告</el-button>
</div>
</div> -->
<!-- 内容区域 -->
<!-- <div class="content-section">
<div class="content-placeholder">
<el-icon><document /></el-icon>
<p>这里是制裁概况的内容区域</p>
<p>请选择上方标签查看不同分析内容</p>
</div>
</div> -->
</div>
</template>
<script setup></script>
<style scoped>
.sanction-container {
width: 100%;
/* max-width: 1200px; */
background-color: #fff;
/* border-radius: 8px; */
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
overflow: hidden;
box-sizing: border-box;
padding-left: 5%;
padding-right: 5%;
}
.page-header {
padding: 24px;
padding-top: 0;
margin-top: 10px;
/* border-bottom: 1px solid #ebeef5; */
display: flex;
justify-content: flex-start;
align-items: center;
gap: 12px;
}
.page-header-img {
width: 64px;
height: 64px;
}
.main-title {
font-size: 20px;
font-weight: 700;
color: rgba(59, 65, 75, 1);
/* color: var(--base-color); */
margin-bottom: 8px;
}
.bill-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 16px;
}
.bill-details {
flex: 1;
margin-right: auto;
}
.bill-name {
font-size: 16px;
color: #606266;
margin-bottom: 4px;
}
.bill-name-en {
font-size: 14px;
color: #909399;
font-style: italic;
}
.date-author {
display: flex;
flex-direction: column;
align-items: flex-end;
}
.date {
font-size: 14px;
color: #606266;
margin-bottom: 4px;
}
.author {
font-size: 14px;
color: #606266;
}
.nav-section {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
background-color: #f8fafc;
border-bottom: 1px solid #ebeef5;
}
.tabs {
display: flex;
gap: 0;
}
.tab-item {
padding: 12px 24px;
font-size: 14px;
color: #606266;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all 0.3s;
}
.tab-item.active {
color: #409eff;
border-bottom-color: #409eff;
background-color: rgba(64, 158, 255, 0.1);
}
.tab-item:hover {
color: #409eff;
}
.action-buttons {
display: flex;
gap: 12px;
}
.content-section {
padding: 24px;
min-height: 400px;
}
.content-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 300px;
color: #909399;
}
.content-placeholder .el-icon {
font-size: 48px;
margin-bottom: 16px;
color: #dcdfe6;
}
.content-placeholder p {
font-size: 16px;
margin-top: 8px;
}
@media (max-width: 768px) {
.bill-info {
flex-direction: column;
align-items: flex-start;
}
.date-author {
align-items: flex-start;
margin-top: 12px;
}
.nav-section {
flex-direction: column;
align-items: flex-start;
gap: 16px;
}
.tabs {
width: 100%;
overflow-x: auto;
}
}
</style>
<template>
<div class="page-container">
<Header />
<!-- 导航标签区域 -->
<div class="nav-section">
<div class="tabs">
<div :class="['tab-item', { active: activeTab === '政令概况' }]" @click="setActiveTab('政令概况')">制裁概况</div>
<div :class="['tab-item', { active: activeTab === '深度挖掘' }]" @click="setActiveTab('深度挖掘')">深度挖掘</div>
<div :class="['tab-item', { active: activeTab === '影响分析' }]" @click="setActiveTab('影响分析')">影响分析</div>
</div>
<div class="action-buttons">
<el-button>政令原文</el-button>
<el-button type="primary">分析报告</el-button>
</div>
</div>
<!-- 内容区域 -->
<div class="content-section">
<!-- <div class="content-placeholder">
<el-icon><document /></el-icon>
<p>这里是制裁概况的内容区域</p>
<p>请选择上方标签查看不同分析内容</p>
</div> -->
<Survey v-if="activeTab === '政令概况'" />
<DepthMine v-if="activeTab === '深度挖掘'" />
<!-- <ImpactAnalysis v-if="activeTab === '影响分析'" /> -->
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import Header from "./header.vue";
import Survey from "./content/survey.vue";
import DepthMine from "./content/depthMine.vue";
// import ImpactAnalysis from "./content/impactAnalysis.vue";
const activeTab = ref("政令概况");
const setActiveTab = tabName => {
activeTab.value = tabName;
};
</script>
<style scoped>
.page-container {
margin: 0px auto;
background-color: rgba(247, 248, 249, 1);
}
.nav-section {
display: flex;
justify-content: space-between;
align-items: center;
/* padding: 16px 24px; */
padding-left: 6%;
padding-right: 6%;
background-color: #fff;
border-bottom: 1px solid #ebeef5;
}
.tabs {
display: flex;
gap: 0;
}
.tab-item {
padding: 12px 24px;
font-size: 14px;
color: #606266;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all 0.3s;
}
.tab-item.active {
color: #409eff;
border-bottom-color: #409eff;
background-color: rgba(64, 158, 255, 0.1);
}
.tab-item:hover {
color: #409eff;
}
.action-buttons {
display: flex;
gap: 12px;
}
.content-section {
padding: 24px;
padding-left: 6%;
padding-right: 6%;
min-height: 400px;
}
.content-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 300px;
color: #909399;
}
.content-placeholder .el-icon {
font-size: 48px;
margin-bottom: 16px;
color: #dcdfe6;
}
.content-placeholder p {
font-size: 16px;
margin-top: 8px;
}
@media (max-width: 768px) {
.bill-info {
flex-direction: column;
align-items: flex-start;
}
.date-author {
align-items: flex-start;
margin-top: 12px;
}
.nav-section {
flex-direction: column;
align-items: flex-start;
gap: 16px;
}
.tabs {
width: 100%;
overflow-x: auto;
}
}
</style>
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
<el-col :span="16"> <el-col :span="16">
<custom-container titleType="primary" title="最新投融资限制政策" :titleIcon="houseIcon" height="450px"> <custom-container titleType="primary" title="最新投融资限制政策" :titleIcon="houseIcon" height="450px">
<template #header-right> <template #header-right>
<el-button type="primary" link @click="handleToDetail"> <el-button type="primary" link>
{{ "查看详情 >" }} {{ "查看详情 >" }}
</el-button> </el-button>
</template> </template>
...@@ -149,7 +149,6 @@ ...@@ -149,7 +149,6 @@
class="box2-main-item" class="box2-main-item"
v-for="(item, index) in warningList" v-for="(item, index) in warningList"
:key="index" :key="index"
@click="handleToDetail"
> >
<div <div
class="item-left" class="item-left"
...@@ -518,6 +517,7 @@ ...@@ -518,6 +517,7 @@
<script setup> <script setup>
import { onMounted, ref, computed } from "vue"; import { onMounted, ref, computed } from "vue";
import scrollToTop from "@/utils/scrollToTop"; import scrollToTop from "@/utils/scrollToTop";
import setChart from "@/utils/setChart";
import * as echarts from "echarts"; import * as echarts from "echarts";
import { DArrowRight, Warning, Search } from "@element-plus/icons-vue"; import { DArrowRight, Warning, Search } from "@element-plus/icons-vue";
import EChart from "@/components/Chart/index.vue"; import EChart from "@/components/Chart/index.vue";
...@@ -587,11 +587,6 @@ const handleBackHome = () => { ...@@ -587,11 +587,6 @@ const handleBackHome = () => {
}); });
}; };
const handleToDetail = () => {
// const route = router.resolve("/exportControl/analysis");
// window.open(route.href, "_blank");
};
// 查看更多风险信号 // 查看更多风险信号
const handleToMoreRiskSignal = () => { const handleToMoreRiskSignal = () => {
const route = router.resolve("/riskSignal"); const route = router.resolve("/riskSignal");
...@@ -1260,63 +1255,6 @@ const handleGetHylyList = async () => { ...@@ -1260,63 +1255,6 @@ const handleGetHylyList = async () => {
} catch (error) {} } catch (error) {}
}; };
const handleClickCate = cate => {
console.log(cate);
activeCate.value = cate.hylymc;
activeHylyId.value = cate.hylyid;
handleGetBillsByType();
};
const navList = ref([
{
icon: headerIcon1,
activeIcno: headerIcon1,
name: "首页",
path: "/home"
},
{
icon: headerIcon2,
activeIcno: headerIcon2,
name: "国家",
path: "/country"
},
{
icon: headerIcon3,
activeIcno: headerIcon3,
name: "领域",
path: "/area"
},
{
icon: headerIcon4,
activeIcno: headerIcon4,
name: "要素",
path: "/home"
},
{
icon: headerIcon5,
activeIcno: headerIcon5,
name: "事件",
path: "/home"
}
]);
const activeNavIndex = ref(0);
const handleClickNav = (index, item) => {
activeNavIndex.value = index;
router.push(item.path);
};
// 绘制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 chart1Data = ref({ const chart1Data = ref({
title: [ title: [
"2024-09", "2024-09",
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<div class="divider"></div> <div class="divider"></div>
<div class="thematic-content"> <div class="thematic-content">
<div class="item-header"> <div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img> <img class="item-header-icon" src="../assets/icon1.png"></img>
<div class="item-header-text">科技博弈历程</div> <div class="item-header-text">科技博弈历程</div>
</div> </div>
......
...@@ -13,8 +13,10 @@ ...@@ -13,8 +13,10 @@
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img> <img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">科技人才对比分析</div> <div class="item-header-text">科技人才对比分析</div>
<div class="item-header-btn"> <div class="item-header-btn">
<img class="item-header-ibtn-con" src="@/assets/images/icon/header-btn.png"></img> <img class="item-header-btn-icon" src="@/assets/images/icon/header-btn.png"></img>
数据来源:美国某某发展基金会 <div style="">
数据来源:美国某某发展基金会
</div>
</div> </div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
...@@ -31,8 +33,10 @@ ...@@ -31,8 +33,10 @@
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img> <img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">科研投入对比分析</div> <div class="item-header-text">科研投入对比分析</div>
<div class="item-header-btn"> <div class="item-header-btn">
<img class="item-header-ibtn-con" src="@/assets/images/icon/header-btn.png"></img> <img class="item-header-btn-icon" src="@/assets/images/icon/header-btn.png"></img>
数据来源:美国某某发展基金会 <div style="">
数据来源:美国某某发展基金会
</div>
</div> </div>
</div> </div>
...@@ -55,8 +59,10 @@ ...@@ -55,8 +59,10 @@
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img> <img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">创新主体对比分析</div> <div class="item-header-text">创新主体对比分析</div>
<div class="item-header-btn"> <div class="item-header-btn">
<img class="item-header-icon" src="@/assets/images/icon/header-btn.png"></img> <img class="item-header-btn-icon" src="@/assets/images/icon/header-btn.png"></img>
数据来源:美国某某发展基金会 <div style="">
数据来源:美国某某发展基金会
</div>
</div> </div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
...@@ -73,21 +79,23 @@ ...@@ -73,21 +79,23 @@
<img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img> <img class="item-header-icon" src="@/assets/images/icon/thematic-card-header-time.png"></img>
<div class="item-header-text">科学数据对比分析</div> <div class="item-header-text">科学数据对比分析</div>
<div class="item-header-btn"> <div class="item-header-btn">
<img class="item-header-ibtn-con" src="@/assets/images/icon/header-btn.png"></img> <img class="item-header-btn-icon" src="@/assets/images/icon/header-btn.png"></img>
数据来源:美国某某发展基金会 <div style="">
数据来源:美国某某发展基金会
</div>
</div> </div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<div style="display: flex;"> <div style="display: flex;">
<div style="display: flex;height: 320px;width: calc(50% - 40px) ;margin: 20px;" id="char7"> <div style="display: flex;height: 360px;width: 433px ; " id="char7">
</div> </div>
<div style="width: 50%;padding-top: 50px;"> <div style="width: 50%;padding-top: 34px;">
<div v-for="value in radar2Data" class="radar2Data-line"> <div v-for="value in radar2Data" class="radar2Data-line">
<div class="radar2Data-circle" :style="{ backgroundColor: value.color }"></div> <div class="radar2Data-circle" :style="{ backgroundColor: value.color }"></div>
<div style=" width: 40px;margin: 0 7px">{{ value.name }}</div> <div style=" margin: 0 5px;font-size: 16px;">{{ value.name }}</div>
<div style="width: calc(100% - 150px) ;padding: 10px;"> <el-progress :percentage="value.percent" <div style="width: 168px ; "> <el-progress :percentage="value.percent" :color="value.color"
:color="value.color" :show-text="false" /></div> :show-text="false" /></div>
<div style=" width: 70px;text-align: right;">{{ value.percent < 50 ? '低依赖' : value.percent < 80 <div style=" width: 70px;text-align: right;">{{ value.percent < 50 ? '低依赖' : value.percent < 80
? '中度依赖' : '高度依赖' }} </div> ? '中度依赖' : '高度依赖' }} </div>
</div> </div>
...@@ -312,7 +320,6 @@ onMounted(() => { ...@@ -312,7 +320,6 @@ onMounted(() => {
display: flex; display: flex;
color: rgba(132, 136, 142, 1); color: rgba(132, 136, 142, 1);
width: calc(100% - 210px);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 16px; font-size: 16px;
...@@ -322,10 +329,23 @@ onMounted(() => { ...@@ -322,10 +329,23 @@ onMounted(() => {
text-align: right; text-align: right;
} }
.item-header-ibtn-con { .item-header-btn-icon {
width: 16px; width: 14px;
height: 16px; height: 16px;
margin-top: 15px; margin-top: 15px;
margin-left: 270px;
margin-right: 4px;
}
.item-header-btn-text {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
} }
} }
...@@ -384,13 +404,17 @@ onMounted(() => { ...@@ -384,13 +404,17 @@ onMounted(() => {
width: 100%; width: 100%;
height: 30px; height: 30px;
margin-top: 18px; margin-top: 18px;
align-items: center;
/* 垂直居中 */
color: rgba(95, 101, 108, 1); color: rgba(95, 101, 108, 1);
font-size: 16px;
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400; font-weight: 400;
line-height: 24px; line-height: 22px;
letter-spacing: 0px; letter-spacing: 0px;
align-items: center; text-align: right;
/* 垂直居中 */
} }
...@@ -400,4 +424,9 @@ onMounted(() => { ...@@ -400,4 +424,9 @@ onMounted(() => {
height: 12px; height: 12px;
border-radius: 50%; border-radius: 50%;
} }
:deep(.el-progress-bar__outer) {
height: 8px !important;
}
</style> </style>
...@@ -20,13 +20,13 @@ ...@@ -20,13 +20,13 @@
</div> </div>
<!-- 卡片 --> <!-- 卡片 -->
<div class="card" :class="[cardPos(item), 'right-side']" :style="widthStyle()" <div class="card" :class="[cardPos(item), 'right-side']" @click="$emit('click-card', item)">
@click="$emit('click-card', item)">
<img :src="`/icon/${item.unit}.png`" class="icon"></img> <img :src="`/icon/${item.unit}.png`" class="icon"></img>
<div class="title">{{ item.time }}</div>
<div class="title" :style="{ <div class="title" :style="{
color: item.unit === '中国' ? ' #CF4F51' : '' color: item.unit === '中国' ? ' #CF4F51' : ''
}">{{ item.title }}</div> }">{{ item.title }}</div>
<div class="time">{{ item.time }}</div>
<div class="content">{{ item.content }}</div> <div class="content">{{ item.content }}</div>
</div> </div>
</div> </div>
...@@ -50,7 +50,15 @@ export default { ...@@ -50,7 +50,15 @@ export default {
}, },
/* 水平位置:按索引均匀分布 */ /* 水平位置:按索引均匀分布 */
leftStyle(i) { leftStyle(i) {
return { left: `${(i * 100) / (this.data.length - 1)}vw` }; // let pos = ``
// if (i === 0) {
// pos = 0
// } else {
// this.linePos(this.data[i - 1]) !== this.linePos(this.data[i]) ? pos = { left: `${(i * 270) - 125}px` } : pos = { left: `${(i * 270)}px` }
// }
return { left: `${(i * 270)}px` }
// return pos;
}, },
/* 卡片上下位置:unit=0 -> 下侧,其余 -> 上侧 */ /* 卡片上下位置:unit=0 -> 下侧,其余 -> 上侧 */
cardPos(item) { cardPos(item) {
...@@ -166,28 +174,30 @@ export default { ...@@ -166,28 +174,30 @@ export default {
.dot.up::after { .dot.up::after {
bottom: 100%; bottom: 100%;
height: 180px height: 240px
} }
.dot.down::after { .dot.down::after {
top: 100%; top: 100%;
height: 180px height: 240px
} }
.card { .card {
position: absolute; position: absolute;
height: 180px; /* 容器 28 */
width: 220px;
height: 176px;
padding: 8px 20px; padding: 8px 20px;
font-size: 14px; font-size: 14px;
cursor: pointer cursor: pointer
} }
.card.up { .card.up {
bottom: 20px bottom: 86px
} }
.card.down { .card.down {
top: 20px; top: 94px;
} }
...@@ -196,15 +206,39 @@ export default { ...@@ -196,15 +206,39 @@ export default {
} }
.title { .title {
/* 美国进一步收紧对华AI芯片出口限制 */
width: 220px;
color: #055fc2; color: #055fc2;
font-size: 18px; font-size: 18px;
font-weight: 700; font-weight: 700;
line-height: 26px line-height: 26px;
margin-top: -25px;
margin-left: 10px;
}
.time {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
margin-left: 10px;
} }
.content { .content {
color: #5f656c; width: 220px;
height: 90px;
color: rgba(59, 65, 75, 1);
margin-left: 10px;
font-family: Microsoft YaHei;
font-size: 16px; font-size: 16px;
line-height: 24px font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
} }
</style> </style>
\ No newline at end of file
...@@ -46,13 +46,16 @@ ...@@ -46,13 +46,16 @@
</div> </div>
<div class="item-card-right"> <div class="item-card-right">
<div style="overflow: auto;height: 400px;"> <div style=" height: 400px;">
<div v-for="(item, index) in technologicalTrends.data" :key="index" style="height: 46px;"> <div v-for="(item, index) in technologicalTrends.data" :key="index" style="height: 46px;">
<div class="list-row"> <div class="list-row">
<div class="item-list-punblier">{{ item.tag1 }}</div> <div class="item-list-punblier">{{ item.tag1 }}</div>
<div class="item-list-content">{{ item.text }}</div> <div class="item-list-content">{{ item.text }}</div>
<div class="item-list-time">{{ item.time }}</div> <div class="item-list-time">{{ item.time }}</div>
<div class="item-list-punblier">{{ item.tag2 }}</div> <div class="item-list-punblier"
:style="{ color: item.tagColor, backgroundColor: item.tagBg, borderColor: item.color }">{{
item.tag2 }}
</div>
</div> </div>
<div class="item-header-divider" /> <div class="item-header-divider" />
</div> </div>
...@@ -66,7 +69,7 @@ ...@@ -66,7 +69,7 @@
<div class="item-header"> <div class="item-header">
<img class="item-header-icon" src="@/assets/images/icon/waring-card-header-icon.png" /> <img class="item-header-icon" src="@/assets/images/icon/waring-card-header-icon.png" />
<div class="item-header-text" style="background-color: #ce4f51">风险信号 <div class="num">{{ warningList.length <div class="item-header-text" style="background-color: #ce4f51">风险信号 <div class="num">{{ warningList.length
}}</div> }}</div>
</div> </div>
</div> </div>
...@@ -130,14 +133,70 @@ const technologicalTrends = ref({ ...@@ -130,14 +133,70 @@ const technologicalTrends = ref({
txt: '2025年9月14日,欧盟委员会宣布通过“地平线欧洲”2025年工作计划投入约73亿欧元的专项资金,增强欧洲的科研创新引擎和', txt: '2025年9月14日,欧盟委员会宣布通过“地平线欧洲”2025年工作计划投入约73亿欧元的专项资金,增强欧洲的科研创新引擎和',
}, },
data: [ data: [
{ tag1: '科研仪器', text: '欧盟投资73亿欧元推进数字化转型', time: '1小时前', tag2: '新能源' }, {
{ tag1: '创新主体', text: '美财政部发布拟议规则限制对华网...', time: '3小时前', tag2: '人工智能' }, "tag1": "科研仪器",
{ tag1: '科技人才', text: '美NIST发布《美国关键和新兴技术....', time: '昨天', tag2: '量子科技' }, "text": "欧盟投资73亿欧元推进数字化转型",
{ tag1: '创新主体', text: '美《开创未来先进计算生态系统:战...', time: '昨天', tag2: '人工智能' }, "time": "1小时前",
{ tag1: '科研仪器', text: '欧盟启动初代“数字地球”系统..', time: '昨天', tag2: '量子科技' }, "tag2": "新能源",
{ tag1: '科研仪器', text: '美NSF投建国家AI可编程云实验室网...', time: '昨天', tag2: '新能源' }, "tagColor": "rgba(250, 140, 22, 1)",
{ tag1: '科研仪器', text: '英启动全球顶尖科技人才引进计划瞄...', time: '昨天', tag2: '新能源' }, "tagBg": "rgba(255, 247, 230, 1)"
{ tag1: '科研仪器', text: '美国家科学基金会致力改进下一代无...', time: '昨天', tag2: '新能源' }, },
{
"tag1": "创新主体",
"text": "美财政部发布拟议规则限制对华网...",
"time": "3小时前",
"tag2": "人工智能",
"tagColor": "rgba(114, 46, 209, 1)",
"tagBg": "rgba(249, 240, 255, 1)"
},
{
"tag1": "科技人才",
"text": "美NIST发布《美国关键和新兴技术....",
"time": "昨天",
"tag2": "量子科技",
"tagColor": "rgba(206, 79, 81, 1)",
"tagBg": "rgba(255, 241, 240, 1)"
},
{
"tag1": "创新主体",
"text": "美《开创未来先进计算生态系统:战...",
"time": "昨天",
"tag2": "人工智能",
"tagColor": "rgba(114, 46, 209, 1)",
"tagBg": "rgba(249, 240, 255, 1)"
},
{
"tag1": "科研仪器",
"text": "欧盟启动初代“数字地球”系统..",
"time": "昨天",
"tag2": "量子科技",
"tagColor": "rgba(206, 79, 81, 1)",
"tagBg": "rgba(255, 241, 240, 1)"
},
{
"tag1": "科研仪器",
"text": "美NSF投建国家AI可编程云实验室网...",
"time": "昨天",
"tag2": "新能源",
"tagColor": "rgba(250, 140, 22, 1)",
"tagBg": "rgba(255, 247, 230, 1)"
},
{
"tag1": "科研仪器",
"text": "英启动全球顶尖科技人才引进计划瞄...",
"time": "昨天",
"tag2": "新能源",
"tagColor": "rgba(250, 140, 22, 1)",
"tagBg": "rgba(255, 247, 230, 1)"
},
{
"tag1": "科研仪器",
"text": "美国家科学基金会致力改进下一代无...",
"time": "昨天",
"tag2": "新能源",
"tagColor": "rgba(250, 140, 22, 1)",
"tagBg": "rgba(255, 247, 230, 1)"
}
], ],
}); });
...@@ -158,10 +217,16 @@ const handleToMoreRiskSignal = () => { ...@@ -158,10 +217,16 @@ const handleToMoreRiskSignal = () => {
<style lang="scss" scoped> <style lang="scss" scoped>
.content-main { .content-main {
width: 100%; // width: 100%;
height: 100%; // height: 100%;
overflow: hidden; // overflow: hidden;
font-family: Microsoft YaHei; // font-family: Microsoft YaHei;
width: 1920px;
margin: 0 auto;
background: url("./assets/bg.png");
background-repeat: no-repeat;
background-color: #fff;
background-size: contain;
} }
.content-title { .content-title {
...@@ -355,7 +420,7 @@ const handleToMoreRiskSignal = () => { ...@@ -355,7 +420,7 @@ const handleToMoreRiskSignal = () => {
.list-row { .list-row {
display: flex; display: flex;
align-items: center; align-items: center;
margin: 10px 0; margin: 5px 0;
height: 40px; height: 40px;
...@@ -382,6 +447,7 @@ const handleToMoreRiskSignal = () => { ...@@ -382,6 +447,7 @@ const handleToMoreRiskSignal = () => {
.item-list-time { .item-list-time {
width: 68px; width: 68px;
text-align: right; text-align: right;
margin-right: 8px;
color: rgba(132, 136, 142, 1); color: rgba(132, 136, 142, 1);
} }
} }
......
...@@ -31,14 +31,22 @@ const getColumnChart = (nameList, series1, series2, isPer) => { ...@@ -31,14 +31,22 @@ const getColumnChart = (nameList, series1, series2, isPer) => {
axisLine: { show: false }, axisLine: { show: false },
axisTick: { show: false }, axisTick: { show: false },
axisLabel: { show: true, color: '#666' }, axisLabel: { show: true, color: '#666' },
splitLine: { show: true, lineStyle: { color: '#ebebeb' } } splitLine: {
show: true,
lineStyle: {
type: "dashed",
color: "#E7F3FF"
}
},
}, },
series: [ series: [
{ {
name: '研究型大学', name: '研究型大学',
type: 'bar', type: 'bar',
data: series1, data: series1,
barWidth: 8, barWidth: 12,
barGap: '60%', // 同一类别内不同系列的间隔
barCategoryGap: "-60%",
label: { show: false }, label: { show: false },
itemStyle: { borderRadius: [8, 8, 0, 0], color: gradBlue } itemStyle: { borderRadius: [8, 8, 0, 0], color: gradBlue }
}, },
...@@ -46,7 +54,7 @@ const getColumnChart = (nameList, series1, series2, isPer) => { ...@@ -46,7 +54,7 @@ const getColumnChart = (nameList, series1, series2, isPer) => {
name: '科技企业', name: '科技企业',
type: 'bar', type: 'bar',
data: series2, data: series2,
barWidth: 8, barWidth: 12,
label: { show: false }, label: { show: false },
itemStyle: { borderRadius: [8, 8, 0, 0], color: gradCyan } itemStyle: { borderRadius: [8, 8, 0, 0], color: gradCyan }
}, },
...@@ -54,7 +62,7 @@ const getColumnChart = (nameList, series1, series2, isPer) => { ...@@ -54,7 +62,7 @@ const getColumnChart = (nameList, series1, series2, isPer) => {
name: '研究机构', name: '研究机构',
type: 'bar', type: 'bar',
data: series2, data: series2,
barWidth: 8, barWidth: 12,
label: { show: false }, label: { show: false },
itemStyle: { borderRadius: [8, 8, 0, 0], color: '#FFC63D' } itemStyle: { borderRadius: [8, 8, 0, 0], color: '#FFC63D' }
} }
......
...@@ -67,7 +67,7 @@ const getMultiLineChart = (dataX, dataY1, dataY2, dataY3, dataY4, dataY5) => { ...@@ -67,7 +67,7 @@ const getMultiLineChart = (dataX, dataY1, dataY2, dataY3, dataY4, dataY5) => {
return { return {
tooltip: { trigger: 'axis', axisPointer: { type: 'cross' } }, tooltip: { trigger: 'axis', axisPointer: { type: 'cross' } },
grid: { top: '5%', right: '0%', bottom: '0%', left: '0%', containLabel: true }, grid: { top: '5%', right: '10%', bottom: '0%', left: '0%', containLabel: true },
xAxis: { type: 'category', boundaryGap: false, data: dataX }, xAxis: { type: 'category', boundaryGap: false, data: dataX },
yAxis: { yAxis: {
......
import * as echarts from "echarts"; import * as echarts from "echarts";
const colors = [
const getBarChart = (nameList, valueList, isPer) => { 'rgba(165, 42, 42, 1)', // 红色
'rgba(0, 0, 128, 1)', // 蓝色
'rgba(0, 128, 128, 1)', // 青色
'rgba(75, 0, 130, 1)', // 紫色
'rgba(255, 165, 0, 1)', // 橙色
'rgba(173, 216, 230, 1)' // 浅蓝色
];
const getRadarChart = () => {
const option = { const option = {
title: { text: '' },
tooltip: {},
radar: { radar: {
radius: '50%', // 关键:缩小整个雷达 radius: '50%',
center: ['50%', '45%'], // 可选:再往下挪一点,避免图例挤在一起 center: ['50%', '45%'],
indicator: [ indicator: [
{ name: '能源', max: 6500 }, { name: '能源领域', max: 100 },
{ name: '集成电路', max: 16000 }, { name: '集成电路', max: 100 },
{ name: '人工智能', max: 30000 }, { name: '生物科技', max: 100 },
{ name: '通信网络', max: 38000 }, { name: '人工智能', max: 100 },
{ name: '量子科技', max: 52000 }, { name: '通信网络', max: 100 },
{ name: '生物科技', max: 25000 } { name: '量子科技', max: 100 }
], ],
axisName: { axisName: {
formatter: '{value}', formatter: '{value}',
color: 'rgba(59, 65, 75, 1)', color: 'rgba(59, 65, 75, 1)',
fontSize: 14, fontSize: 16,
fontWeight: 400 fontWeight: 400
} }
}, },
series: [ series: [
{ {
name: 'Budget vs spending', name: '科技领域表现',
type: 'radar', type: 'radar',
symbol: 'none', symbol: 'none',
data: [ data: [
{ {
value: [4200, 3000, 20000, 35000, 50000, 18000], "value": [20, 95, 30, 85, 70, 60],
name: '中国', "name": "中国",
areaStyle: { color: 'rgba(10, 87, 166, 0.2)' } "areaStyle": { "color": "rgba(165, 42, 42, 0.2)" },
lineStyle: {
width: 1.5, // 设置线条宽度为2
color: 'rgba(165, 42, 42, 1)' // 设置线条颜色
}
}, },
{ {
value: [5000, 14000, 28000, 26000, 42000, 21000], "value": [90, 40, 85, 20, 60, 75],
name: '美国', "name": "美国",
areaStyle: { color: 'rgba(206, 79, 81, 0.2)' } "areaStyle": { "color": "rgba(0, 0, 128, 0.2)" },
lineStyle: {
width: 1.5, // 设置线条宽度为2
color: 'rgba(0, 0, 128, 1)' // 设置线条颜色
}
}, },
{ {
value: [4000, 14000, 18000, 21000, 32000, 10000], "value": [80, 68, 92, 82, 58, 88],
name: '欧盟', "name": "欧盟",
areaStyle: { color: 'rgba(250, 140, 22, 0.2)' } "areaStyle": { "color": "rgba(0, 128, 128, 0.2)" },
lineStyle: {
width: 1.5, // 设置线条宽度为2
color: 'rgba(0, 128, 128, 1)' // 设置线条颜色
}
}, },
{ {
value: [4000, 14000, 18000, 21000, 32000, 10000], "value": [57, 81, 76, 91, 87, 67],
name: '英国', "name": "英国",
areaStyle: { color: 'rgba(250, 140, 22, 0.2)' } "areaStyle": { "color": "rgba(75, 0, 130, 0.2)" },
lineStyle: {
width: 1.5, // 设置线条宽度为2
color: 'rgba(75, 0, 130, 1)' // 设置线条颜色
}
}, },
{ {
value: [4000, 14000, 18000, 21000, 32000, 10000], "value": [93, 59, 79, 89, 69, 83],
name: '日本', "name": "日本",
areaStyle: { color: 'rgba(250, 140, 22, 0.2)' } "areaStyle": { "color": "rgba(255, 165, 0, 0.2)" },
lineStyle: {
width: 1.5, // 设置线条宽度为2
color: 'rgba(255, 165, 0, 1)' // 设置线条颜色
}
}, },
{ {
value: [4000, 14000, 18000, 21000, 32000, 10000], "value": [86, 56, 77, 94, 80, 66],
name: '韩国', "name": "韩国",
areaStyle: { color: 'rgba(250, 140, 22, 0.2)' } "areaStyle": { "color": "rgba(173, 216, 230,0.2)" },
lineStyle: {
width: 1.5, // 设置线条宽度为2
color: 'rgba(173, 216, 230, 1)' // 设置线条颜色
}
} }
] ]
} }
] ]
} };
return option return option;
} };
export default getBarChart export default getRadarChart;
\ No newline at end of file \ No newline at end of file
...@@ -914,8 +914,9 @@ onMounted(() => {}); ...@@ -914,8 +914,9 @@ onMounted(() => {});
} }
.news-box-title { .news-box-title {
height: 48px;
line-height: 24px;
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 16px; font-size: 16px;
font-weight: 700; font-weight: 700;
...@@ -936,6 +937,7 @@ onMounted(() => {}); ...@@ -936,6 +937,7 @@ onMounted(() => {});
} }
.news-box-title-small { .news-box-title-small {
margin-top: 3px;
height: 22px; height: 22px;
color: rgba(95, 101, 108, 1); color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
...@@ -981,15 +983,18 @@ onMounted(() => {}); ...@@ -981,15 +983,18 @@ onMounted(() => {});
background-position: center center; background-position: center center;
.talk-title { .talk-title {
width: 40%; width: 220px;
height: 24px;
color: rgba(59, 65, 75, 1); color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 16px; font-size: 16px;
font-weight: 700; font-weight: 700;
line-height: 24px; line-height: 24px;
letter-spacing: 0px; letter-spacing: 1px;
text-align: left; text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
} }
} }
......
...@@ -5,6 +5,12 @@ ...@@ -5,6 +5,12 @@
<div v-for="(item, index) in sourceLibraryData" :key="index" class="source-library-card"> <div v-for="(item, index) in sourceLibraryData" :key="index" class="source-library-card">
<div class="source-library-avatar-wrapper"> <div class="source-library-avatar-wrapper">
<img :src="item.avatar" alt="" class="source-library-avatar" /> <img :src="item.avatar" alt="" class="source-library-avatar" />
<div class="person-tags">
<div class="person-tag-bg" v-for="(tag, tIdx) in item.icon" :key="tIdx">
<img :src="'/public/icon/header-icon' + tag + '.png'" class="tag-icon" alt="tag" />
</div>
</div>
</div> </div>
<div class="source-library-text-content"> <div class="source-library-text-content">
<div style=" width: 240px;"> <div style=" width: 240px;">
...@@ -77,6 +83,28 @@ const handlePageChange = p => { ...@@ -77,6 +83,28 @@ const handlePageChange = p => {
margin-right: 18px; margin-right: 18px;
} }
.person-tags {
display: flex;
margin-top: -20px;
width: 42px;
padding-left: 28px;
text-align: center;
}
.person-tag-bg {
/* 椭圆 6 */
width: 32px;
height: 32px;
background: rgba(255, 255, 255, 0.8);
border-radius: 50%;
}
.tag-icon {
width: 24px;
height: 24px;
object-fit: contain;
}
.source-library-avatar { .source-library-avatar {
/* 椭圆 142 */ /* 椭圆 142 */
width: 88px; width: 88px;
...@@ -140,7 +168,7 @@ const handlePageChange = p => { ...@@ -140,7 +168,7 @@ const handlePageChange = p => {
} }
.page { .page {
width: 1221px; width: 1600px;
height: 40px; height: 40px;
display: flex; display: flex;
align-items: center; align-items: center;
......
<template>
<div ref="map" style="width: 1600px; height: 551px"></div>
<div
style="width: 1231px; height: 72px; margin-top: -55px; background: linear-gradient(to top, #DAEBFD, #ffffff);margin-left: 182px">
<div style="width: 1231px; height: 40px; display: flex;justify-content: space-between;">
<div style="display: flex;align-self: center;">
<div class="time-btn">
</div>
<div class="time-btn">
</div>
<div class="time-btn">
重置
</div>
</div>
<div style="display: flex;align-self: center;">
<div>
当前时间:
</div>
<input></input>
<div style="margin: 0 10px 0 40px;color: #04295A;"> 刻度</div>
<select name="firstSelect" id="firstSelect">
<option value="option1">周制</option>
</select>
<div style="margin: 0 10px 0 40px;color: #04295A;">速率</div>
<select name="secondSelect" id="secondSelect" style="margin-right: 20px;">
<option value="optionA">1X</option>
<option value="optionB">2X</option>
</select>
</div>
</div>
<div ref=" timeLineChart" style="width: 1231px; height: 30px;background-color: #6091D6; "></div>
</div>
</template>
<script>
import * as echarts from "echarts";
import worldJson from "@/assets/json/world.json";
export default {
name: "MapAnimation",
mounted() {
this.initMap();
},
methods: {
initMap() {
// 注册自定义地图数据
echarts.registerMap("China", worldJson);
const chart = echarts.init(this.$refs.map);
const option = {
// timeline: {
// autoplay: true,
// playInterval: 2000,
// data: ["9月23日"]
// },
grid: {
left: "10%",
right: "10%",
bottom: "10%",
top: "10%",
containLabel: true
},
geo: {
map: "China",
roam: true,
label: {
emphasis: {
show: false,
color: "#fff"
}
},
silent: true,
itemStyle: {
areaColor: "#F6FAFF",
borderColor: "#B9DCFF"
}
},
series: [
{
name: "行程",
type: "effectScatter",
coordinateSystem: "geo",
data: [
{
time: "2025-02-01",
text: "随美国总统特朗普进行国事访问",
value: [116.46, 39.92],
itemStyle: { color: "#ffcc00" }
},
{
time: "2025-02-01",
text: "出席中国发展高层论坛2025年年会",
value: [116.46, 39.92],
itemStyle: { color: "#ffcc00" }
},
{
time: "2025-02-01",
text: "与民主党领导人查克·舒默及哈基姆...",
value: [1.46, 39.92],
itemStyle: { color: "#ffcc00" }
},
{
time: "2025-02-01",
text: "与阿拉伯国家领导人会晤,商讨加...",
value: [116.46, -44.92],
itemStyle: { color: "#ffcc00" }
},
{
time: "2025-02-01",
text: "对印度进行为期四天的访问,与总理...",
value: [78.1, 20.7],
itemStyle: { color: "#ffcc00" }
}
],
symbolSize: 10,
showEffectOn: "render",
rippleEffect: {
brushType: "stroke"
},
label: {
normal: {
show: true,
formatter: function (params) {
var name = params.name;
var value = params.data.datas;
var text = `{fline|${value}}\n{tline|${name}}{img|${img}}`;
return text;
},
color: '#fff',
rich: {
fline: {
padding: [0, 25],
color: '#fff',
textShadowColor: '#030615',
textShadowBlur: '0',
textShadowOffsetX: 1,
textShadowOffsetY: 1,
fontSize: 14,
fontWeight: 400,
},
img: {
backgroundColor: {
image: '/testData/image 21.png' // 图片URL
},
height: 50, // 图片高度
width: 50 // 图片宽度
},
tline: {
padding: [0, 27],
color: '#ABF8FF',
fontSize: 12,
},
},
},
emphasis: {
show: true,
},
},
label: {
show: true,
position: "right",
offset: [5, 0],
borderColor: "rgba(174, 214, 255, 1)",
backgroundColor: "rgba(255, 255, 255, 0.8)",
formatter: params => {
const { time, text } = params.data; // 👈 从 params.data 取
return `{time|${time}} \n {text|${text}项}`;
},
rich: {
time: {
fontSize: 16,
fontFamily: "Microsoft YaHei",
fontWeight: 700,
lineHeight: 30,
color: "rgba(5, 95, 194, 1)"
},
text: {
fontSize: 14,
fontFamily: "Microsoft YaHei",
fontWeight: 400,
lineHeight: 22,
color: "rgb(95, 101, 108)"
}
}
},
itemStyle: {
color: "#ddb926",
shadowBlur: 10,
shadowColor: "#333"
}
}
]
};
chart.setOption(option);
// const chart2 = echarts.init(this.$refs.timeLineChart);
// const option2 = {
// xAxis: {
// type: "time",
// position: "top",
// axisLine: {
// show: true,
// lineStyle: {
// color: "#000"
// }
// },
// axisTick: {
// show: false
// },
// axisLabel: {
// formatter: "{value}日",
// color: "#000"
// },
// splitLine: {
// show: true
// },
// data: [
// "2024-03-25",
// "2024-04-08",
// "2024-04-15",
// "2024-04-22",
// "2024-04-29",
// "2024-05-06",
// "2024-05-13",
// "2024-05-20",
// "2024-05-27",
// "2024-06-03",
// "2024-06-10",
// "2024-06-17",
// "2024-06-24",
// "2024-07-01",
// "2024-07-08",
// "2024-07-15",
// "2024-07-22",
// "2024-07-29"
// ]
// },
// yAxis: {
// type: "value",
// show: false
// },
// series: [
// {
// data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
// type: "line",
// areaStyle: {},
// emphasis: {
// focus: "series"
// }
// }
// ],
// visualMap: {
// show: false,
// dimension: 1,
// pieces: [{ gt: 0, lte: 1, color: "#ffcc00" }]
// }
// };
// chart2.setOption(option2);
}
}
};
</script>
<style scoped>
#map {
width: 1600px;
height: 581px;
}
.time-btn {
color: #04295A;
background-color: #F9FDFE;
border: 1px solid #04295A;
padding: 0 10px;
margin: 0 10px;
}
</style>
<template> <template>
<div ref="map" style="width: 1600px; height: 551px"></div> <div ref="map" style="width: 1600px; height: 551px"></div>
<div <div
style="width: 1231px; height: 72px; margin-top: -55px; background: linear-gradient(to top, #DAEBFD, #ffffff);margin-left: 182px"> style="width: 1231px; height: 72px; margin-top: -55px; background: linear-gradient(to top, #DAEBFD, #ffffff); margin-left: 182px">
<div style="width: 1231px; height: 40px; display: flex;justify-content: space-between;"> <div style="width: 1231px; height: 40px; display: flex; justify-content: space-between;">
<div style="display: flex;align-self: center;"> <div style="display: flex; align-self: center;">
<div class="time-btn"> <div class="time-btn">
</div> </div>
...@@ -14,16 +14,16 @@ ...@@ -14,16 +14,16 @@
重置 重置
</div> </div>
</div> </div>
<div style="display: flex;align-self: center;"> <div style="display: flex; align-self: center;">
<div> <div>
当前时间: 当前时间:
</div> </div>
<input></input> <input></input>
<div style="margin: 0 10px 0 40px;color: #04295A;"> 刻度</div> <div style="margin: 0 10px 0 40px; color: #04295A;">刻度</div>
<select name="firstSelect" id="firstSelect"> <select name="firstSelect" id="firstSelect">
<option value="option1">周制</option> <option value="option1">周制</option>
</select> </select>
<div style="margin: 0 10px 0 40px;color: #04295A;">速率</div> <div style="margin: 0 10px 0 40px; color: #04295A;">速率</div>
<select name="secondSelect" id="secondSelect" style="margin-right: 20px;"> <select name="secondSelect" id="secondSelect" style="margin-right: 20px;">
<option value="optionA">1X</option> <option value="optionA">1X</option>
<option value="optionB">2X</option> <option value="optionB">2X</option>
...@@ -31,15 +31,13 @@ ...@@ -31,15 +31,13 @@
</div> </div>
</div> </div>
<div ref=" timeLineChart" style="width: 1231px; height: 30px;background-color: #6091D6; "></div> <div ref="timeLineChart" style="width: 1231px; height: 30px; background-color: #6091D6;"></div>
</div> </div>
</template> </template>
<script> <script>
import * as echarts from "echarts"; import * as echarts from "echarts";
import worldJson from "@/assets/json/world.json"; import worldJson from "@/assets/json/world.json";
export default { export default {
name: "MapAnimation", name: "MapAnimation",
mounted() { mounted() {
...@@ -49,15 +47,46 @@ export default { ...@@ -49,15 +47,46 @@ export default {
initMap() { initMap() {
// 注册自定义地图数据 // 注册自定义地图数据
echarts.registerMap("China", worldJson); echarts.registerMap("China", worldJson);
const eventsData = [
{
time: "9月23日",
text: "随美国总统特朗普进行国事访问",
lon: 116.46,
lat: 39.92,
avatar: "/testData/united_states 1 copy.png"
},
{
time: "9月23日",
text: "出席中国发展高层论坛2025年年会",
lon: 116.46,
lat: 39.92,
avatar: "/testData/united_states 1 copy.png"
},
{
time: "9月23日",
text: "与民主党领导人查克·舒默及哈基姆...",
lon: 1.46,
lat: 39.92,
avatar: "/testData/united_states 1 copy.png"
},
{
time: "9月23日",
text: "与阿拉伯国家领导人会晤,商讨加...",
lon: 116.46,
lat: -44.92,
avatar: "/testData/united_states 1 copy.png"
},
{
time: "9月23日",
text: "对印度进行为期四天的访问,与总理...",
lon: 78.1,
lat: 20.7,
avatar: "/testData/united_states 1 copy.png"
}
];
const chart = echarts.init(this.$refs.map); const chart = echarts.init(this.$refs.map);
const option = { const option = {
// timeline: {
// autoplay: true,
// playInterval: 2000,
// data: ["9月23日"]
// },
grid: { grid: {
left: "10%", left: "10%",
right: "10%", right: "10%",
...@@ -85,71 +114,31 @@ export default { ...@@ -85,71 +114,31 @@ export default {
name: "行程", name: "行程",
type: "effectScatter", type: "effectScatter",
coordinateSystem: "geo", coordinateSystem: "geo",
data: [ data: eventsData.map(item => ({
{ value: [item.lon, item.lat],
time: "2025-02-01", time: item.time,
text: "随美国总统特朗普进行国事访问", text: item.text,
value: [116.46, 39.92], avatar: item.avatar,
itemStyle: { color: "#ffcc00" } itemStyle: { color: "#ffcc00" }
}, })),
{
time: "2025-02-01",
text: "出席中国发展高层论坛2025年年会",
value: [116.46, 39.92],
itemStyle: { color: "#ffcc00" }
},
{
time: "2025-02-01",
text: "与民主党领导人查克·舒默及哈基姆...",
value: [1.46, 39.92],
itemStyle: { color: "#ffcc00" }
},
{
time: "2025-02-01",
text: "与阿拉伯国家领导人会晤,商讨加...",
value: [116.46, -44.92],
itemStyle: { color: "#ffcc00" }
},
{
time: "2025-02-01",
text: "对印度进行为期四天的访问,与总理...",
value: [78.1, 20.7],
itemStyle: { color: "#ffcc00" }
}
],
symbolSize: 10, symbolSize: 10,
showEffectOn: "render", showEffectOn: "render",
rippleEffect: { rippleEffect: {
brushType: "stroke" brushType: "stroke"
}, },
label: { // label: {
show: true, // normal: {
position: "right", // show: true,
offset: [5, 0], // formatter: params => {
borderColor: "rgba(174, 214, 255, 1)", // const { time, text } = eventsData[params.dataIndex];
// return `{time|${time}} \n {text|${text}}`;
backgroundColor: "rgba(255, 255, 255, 0.8)", // },
formatter: params => { // rich: {
const { time, text } = params.data; // 👈 从 params.data 取 // time: { fontSize: 16, color: 'rgba(5, 95, 194, 1)' },
return `{time|${time}} \n {text|${text}项}`; // text: { fontSize: 14, color: 'rgb(95, 101, 108)' }
}, // }
rich: { // }
time: { // },
fontSize: 16,
fontFamily: "Microsoft YaHei",
fontWeight: 700,
lineHeight: 30,
color: "rgba(5, 95, 194, 1)"
},
text: {
fontSize: 14,
fontFamily: "Microsoft YaHei",
fontWeight: 400,
lineHeight: 22,
color: "rgb(95, 101, 108)"
}
}
},
itemStyle: { itemStyle: {
color: "#ddb926", color: "#ddb926",
shadowBlur: 10, shadowBlur: 10,
...@@ -158,8 +147,16 @@ export default { ...@@ -158,8 +147,16 @@ export default {
} }
] ]
}; };
chart.setOption(option); chart.setOption(option);
// 添加 graphic 元素并设置其位置
this.updateGraphics(chart, eventsData);
// 监听地图缩放和移动事件,以更新 graphic 的位置
chart.on('georoam', () => {
this.updateGraphics(chart, eventsData);
});
const chart2 = echarts.init(this.$refs.timeLineChart); const chart2 = echarts.init(this.$refs.timeLineChart);
const option2 = { const option2 = {
...@@ -225,6 +222,62 @@ export default { ...@@ -225,6 +222,62 @@ export default {
}; };
chart2.setOption(option2); chart2.setOption(option2);
},
updateGraphics(chart, eventsData) {
const graphics = eventsData.map((event, index) => {
const position = chart.convertToPixel({ geoIndex: 0 }, [event.lon, event.lat]);
return {
type: 'group',
position: position,
children: [
{
type: 'image',
x: -170, y: -72,
style: {
image: "/icon/map-text-bg.png",
borderWidth: 2,
borderColor: '#1890ff', width: 339, height: 72
}
},
{
type: 'image',
x: -160, y: -63,
style: {
image: event.avatar,
borderWidth: 2,
borderColor: '#1890ff', width: 42, height: 42
}
}, {
type: 'text',
x: -106, y: -63,
style: {
text: event.time,
fontSize: 16,
fontWeight: '800',
fill: 'rgba(5, 95, 194, 1)', // 文字颜色(ECharts 中用 fill,不是 color)
textAlign: 'left'
}
},
{
type: 'text',
x: -106, y: -40,
style: {
text: event.text,
fontSize: 16,
fontWeight: '400',
fill: 'rgba(59, 65, 75, 1)', // 文字颜色(ECharts 中用 fill,不是 color)
textAlign: 'left'
}
}
]
};
});
chart.setOption({
graphic: graphics
});
chart.resize(); // 强制刷新图表
} }
} }
}; };
...@@ -234,14 +287,14 @@ export default { ...@@ -234,14 +287,14 @@ export default {
#map { #map {
width: 1600px; width: 1600px;
height: 581px; height: 581px;
font-family: Microsoft YaHei;
} }
.time-btn { .time-btn {
color: #04295A; color: #04295A;
background-color: #F9FDFE; background-color: #F9FDFE;
border: 1px solid #04295A; border: 1px solid #04295A;
padding: 0 10px; padding: 0 10px;
margin: 0 10px; margin: 0 10px;
} }
</style> </style>
\ No newline at end of file
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
<div class="box1-header"> <div class="box1-header">
<div class="box1-header-left"> <div class="box1-header-left">
<div class="icon"> <div class="icon">
<img src="./assets/images/box1-header-icon.png" alt="" /> <img src="./assets/images/TechnologyFigures-icon4.png" alt="" />
</div> </div>
<div class="title">{{ "人物新闻动态" }}</div> <div class="title">{{ "人物新闻动态" }}</div>
</div> </div>
...@@ -128,7 +128,7 @@ ...@@ -128,7 +128,7 @@
<div class="box3-header"> <div class="box3-header">
<div class="box3-header-left"> <div class="box3-header-left">
<div class="box3-header-icon"> <div class="box3-header-icon">
<img src="./assets/images/header-news.png" alt="" /> <img src="./assets/images/TechnologyFigures-icon3.png" alt="" />
</div> </div>
<!-- <div class="box3-header-title">{{ "人物动向" }}</div> --> <!-- <div class="box3-header-title">{{ "人物动向" }}</div> -->
<div class="header-title" <div class="header-title"
...@@ -178,7 +178,7 @@ ...@@ -178,7 +178,7 @@
<div class="box5-header"> <div class="box5-header">
<div class="box5-header-left"> <div class="box5-header-left">
<div class="box5-header-icon"> <div class="box5-header-icon">
<img src="./assets/images/box3-header-icon.png" alt="" <img src="./assets/images/TechnologyFigures-icon1.png" alt=""
style="margin: 13px 21px 13px 21px; height: 22px" /> style="margin: 13px 21px 13px 21px; height: 22px" />
<div class="box5-header-title">{{ "科技人物观点词云" }}</div> <div class="box5-header-title">{{ "科技人物观点词云" }}</div>
</div> </div>
...@@ -200,7 +200,7 @@ ...@@ -200,7 +200,7 @@
<div class="box6"> <div class="box6">
<div class="box6-header" style="width: 790px"> <div class="box6-header" style="width: 790px">
<div class="header-icon"> <div class="header-icon">
<img src="./assets/images/box6-header-icon.png" alt="" /> <img src="./assets/images/box3-header-icon.png" alt="" />
</div> </div>
<div class="header-title" <div class="header-title"
style="display: flex; width: 740px; justify-content: space-between; align-items: center"> style="display: flex; width: 740px; justify-content: space-between; align-items: center">
...@@ -223,7 +223,7 @@ ...@@ -223,7 +223,7 @@
<div class="box7-header"> <div class="box7-header">
<div class="box7-header-left"> <div class="box7-header-left">
<div class="box7-header-icon"> <div class="box7-header-icon">
<img src="./assets/images/box3-header-icon.png" alt="" /> <img src="./assets/images/TechnologyFigures-icon2.png" alt="" />
</div> </div>
<div class="box7-header-title">{{ "科技人物类型" }}</div> <div class="box7-header-title">{{ "科技人物类型" }}</div>
</div> </div>
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
<div class="box8-header"> <div class="box8-header">
<div class="box8-header-left"> <div class="box8-header-left">
<div class="box8-header-icon"> <div class="box8-header-icon">
<img src="./assets/images/box6-header-icon.png" alt="" /> <img src="./assets/images/TechnologyFigures-icon2.png" alt="" />
</div> </div>
<div style="display: flex; width: 730px; justify-content: space-between; align-items: center"> <div style="display: flex; width: 730px; justify-content: space-between; align-items: center">
<div class="box8-header-title">{{ "主要人物涉华观点统计" }}</div> <div class="box8-header-title">{{ "主要人物涉华观点统计" }}</div>
...@@ -839,7 +839,7 @@ onMounted(() => { ...@@ -839,7 +839,7 @@ onMounted(() => {
line-height: 47px; line-height: 47px;
color: rgba(132, 136, 142, 1); color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 14px; font-size: 16px;
font-weight: 400; font-weight: 400;
} }
} }
......
...@@ -4,111 +4,127 @@ ...@@ -4,111 +4,127 @@
"title": "美国总统(2017-2021、2025-至今),共和党党员", "title": "美国总统(2017-2021、2025-至今),共和党党员",
"tag": "行政主管", "tag": "行政主管",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#1677FF", "#BAE0FF", "#E6F4FF"] "colorArray": ["#1677FF", "#BAE0FF", "#E6F4FF"],
"icon": ["1"]
}, },
{ {
"name": "詹姆斯·戴维·万斯", "name": "詹姆斯·戴维·万斯",
"title": "美国副总统、参议院议长、共和党全国委员会财务主席", "title": "美国副总统、参议院议长、共和党全国委员会财务主席",
"tag": "行政主管", "tag": "行政主管",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#1677FF", "#BAE0FF", "#E6F4FF"] "colorArray": ["#1677FF", "#BAE0FF", "#E6F4FF"],
"icon": []
}, },
{ {
"name": "黄仁勋", "name": "黄仁勋",
"title": "NVIDIA公司创始人兼首席执行官,美国工程院院士", "title": "NVIDIA公司创始人兼首席执行官,美国工程院院士",
"tag": "科技企业领袖", "tag": "科技企业领袖",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#13A8A8", "#87E8DE", "#E6FFFFB"] "colorArray": ["#13A8A8", "#87E8DE", "#E6FFFFB"],
"icon": ["1"]
}, },
{ {
"name": "马尔科·鲁比奥", "name": "马尔科·鲁比奥",
"title": "美国国务卿,美国总统国家安全事务临时助理", "title": "美国国务卿,美国总统国家安全事务临时助理",
"tag": "行政主管", "tag": "行政主管",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#1677FF", "#BAE0FF", "#E6F4FF"] "colorArray": ["#1677FF", "#BAE0FF", "#E6F4FF"],
"icon": []
}, },
{ {
"name": "埃隆·马斯克", "name": "埃隆·马斯克",
"title": "特斯拉创始人兼首席执行官、SpaceX、美国党创始人", "title": "特斯拉创始人兼首席执行官、SpaceX、美国党创始人",
"tag": "科技企业领袖", "tag": "科技企业领袖",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#13A8A8", "#87E8DE", "#E6FFFFB"] "colorArray": ["#13A8A8", "#87E8DE", "#E6FFFFB"],
"icon": ["1"]
}, },
{ {
"name": "乔迪·阿灵顿", "name": "乔迪·阿灵顿",
"title": "共和党党员,美国国会众议院议员,预算委员会主席", "title": "共和党党员,美国国会众议院议员,预算委员会主席",
"tag": "国会议员", "tag": "国会议员",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#FAAD14", "#FFE58F", "#FFFBE6"] "colorArray": ["#FAAD14", "#FFE58F", "#FFFBE6"],
"icon": []
}, },
{ {
"name": "霍华德·卢特尼克", "name": "霍华德·卢特尼克",
"title": "美国商务部长", "title": "美国商务部长",
"tag": "行政主管", "tag": "行政主管",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#1677FF", "#BAE0FF", "#E6F4FF"] "colorArray": ["#1677FF", "#BAE0FF", "#E6F4FF"],
"icon": ["1"]
}, },
{ {
"name": "蒂姆·库克", "name": "蒂姆·库克",
"title": "苹果公司首席执行官,清华大学经济管理学院顾问委员会主席", "title": "苹果公司首席执行官,清华大学经济管理学院顾问委员会主席",
"tag": "科技企业领袖", "tag": "科技企业领袖",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#13A8A8", "#87E8DE", "#E6FFFFB"] "colorArray": ["#13A8A8", "#87E8DE", "#E6FFFFB"],
"icon": []
}, },
{ {
"name": "朱棣文", "name": "朱棣文",
"title": "第12任美国能源部部长,主要研究领域为原子物理、激光科学", "title": "第12任美国能源部部长,主要研究领域为原子物理、激光科学",
"tag": "顶级科学家", "tag": "顶级科学家",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#722ED1", "#D3ADF7", "#F9F0FF"] "colorArray": ["#722ED1", "#D3ADF7", "#F9F0FF"],
"icon": ["1"]
}, },
{ {
"name": "约翰·图恩", "name": "约翰·图恩",
"title": "共和党党员,美国国会众议院议员", "title": "共和党党员,美国国会众议院议员",
"tag": "国会议员", "tag": "国会议员",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#FAAD14", "#FFE58F", "#FFFBE6"] "colorArray": ["#FAAD14", "#FFE58F", "#FFFBE6"],
"icon": []
}, },
{ {
"name": "珍妮弗·道德纳", "name": "珍妮弗·道德纳",
"title": "主要研究领域为RNA领域和基因编辑技术", "title": "主要研究领域为RNA领域和基因编辑技术",
"tag": "顶级科学家", "tag": "顶级科学家",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#722ED1", "#D3ADF7", "#F9F0FF"] "colorArray": ["#722ED1", "#D3ADF7", "#F9F0FF"],
"icon": ["1"]
}, },
{ {
"name": "迈克·约翰逊", "name": "迈克·约翰逊",
"title": "美国众议院议长", "title": "美国众议院议长",
"tag": "国会议员", "tag": "国会议员",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#FAAD14", "#FFE58F", "#FFFBE6"] "colorArray": ["#FAAD14", "#FFE58F", "#FFFBE6"],
"icon": []
}, },
{ {
"name": "亚当·史密斯", "name": "亚当·史密斯",
"title": "美国国会众议院议员,众议院军事委员会民主党领袖", "title": "美国国会众议院议员,众议院军事委员会民主党领袖",
"tag": "国会议员", "tag": "国会议员",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#FAAD14", "#FFE58F", "#FFFBE6"] "colorArray": ["#FAAD14", "#FFE58F", "#FFFBE6"],
"icon": ["1"]
}, },
{ {
"name": "查尔斯·本内特", "name": "查尔斯·本内特",
"title": "美国国家科学院院士、美国物理学会院士,量子信息论主要创立者", "title": "美国国家科学院院士、美国物理学会院士,量子信息论主要创立者",
"tag": "顶级科学家", "tag": "顶级科学家",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#722ED1", "#D3ADF7", "#F9F0FF"] "colorArray": ["#722ED1", "#D3ADF7", "#F9F0FF"],
"icon": []
}, },
{ {
"name": "桑达尔·皮查伊", "name": "桑达尔·皮查伊",
"title": "谷歌母公司Alphabet首席执行官", "title": "谷歌母公司Alphabet首席执行官",
"tag": "科技企业领袖", "tag": "科技企业领袖",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#13A8A8", "#87E8DE", "#E6FFFFB"] "colorArray": ["#13A8A8", "#87E8DE", "#E6FFFFB"],
"icon": ["1"]
}, },
{ {
"name": "威康·汤姆逊", "name": "威康·汤姆逊",
"title": "美国国家科学院院士、美国物理学会院士,量子信息论主要创立者", "title": "美国国家科学院院士、美国物理学会院士,量子信息论主要创立者",
"tag": "顶级科学家", "tag": "顶级科学家",
"avatar": "/public/testData/data2.png", "avatar": "/public/testData/data2.png",
"colorArray": ["#722ED1", "#D3ADF7", "#F9F0FF"] "colorArray": ["#722ED1", "#D3ADF7", "#F9F0FF"],
"icon": []
} }
] ]
...@@ -36,12 +36,12 @@ ...@@ -36,12 +36,12 @@
</div> </div>
</div> </div>
<div class="btn-box"> <div class="btn-box">
<div class="btn"> <!-- <div class="btn">
<div class="icon"> <div class="icon">
<img src="./images/btn-icon1.png" alt="" /> <img src="./images/btn-icon1.png" alt="" />
</div> </div>
<div class="text">{{ "查看官网" }}</div> <div class="text">{{ "查看官网" }}</div>
</div> </div> -->
<div class="btn"> <div class="btn">
<div class="icon"> <div class="icon">
<img src="./images/btn-icon2.png" alt="" /> <img src="./images/btn-icon2.png" alt="" />
...@@ -64,7 +64,8 @@ ...@@ -64,7 +64,8 @@
</div> </div>
</div> </div>
<div class="main"> <div class="main">
<ReportAnalysis></ReportAnalysis> <ReportAnalysis v-if="tabActiveName === '报告分析'"></ReportAnalysis>
<PolicyTracking v-else></PolicyTracking>
</div> </div>
</div> </div>
</template> </template>
...@@ -73,6 +74,7 @@ ...@@ -73,6 +74,7 @@
import { ref } from "vue"; import { ref } from "vue";
import ReportAnalysis from './reportAnalysis/index.vue' import ReportAnalysis from './reportAnalysis/index.vue'
import PolicyTracking from './policyTracking/index.vue'
const tabActiveName = ref("报告分析"); const tabActiveName = ref("报告分析");
......
<template>
<div class="wrap">
<div class="left">
<div class="box1">
<div class="box-header">
<div class="header-left"></div>
<div class="title">政策建议落实情况</div>
<div class="header-right">
<div class="icon">
<img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div>
<div class="box1-main">
<div class="box1-item" v-for="(item, index) in box1Data" :key="index">
<div class="left">
{{ item.id }}
</div>
<div class="center">
<div class="title">{{ item.title }}</div>
<div class="tag-box">
<div class="tag" v-for="(val, idx) in item.tagList" :key="idx">
{{ val }}
</div>
</div>
<div class="file-box">
<div class="file-item" v-for="(vall, idxx) in item.fileList" :key="idxx">
<div class="file-item-left">{{ vall.type }}</div>
<div class="file-item-center">{{ vall.name }}</div>
<div class="file-item-right">
<img src="@/assets/images/icon-right-circle.png" alt="" />
</div>
</div>
</div>
</div>
<div class="right">
<div class="text">
{{ "查看智库原文" }}
</div>
<div class="icon">
<img src="@/assets/icons/open.png" alt="" />
</div>
</div>
</div>
</div>
<div class="box1-footer">
<div class="info">
{{ `共105项调查` }}
</div>
<div class="page-box">
<el-pagination :page-size="10" background layout="prev, pager, next" :total="120" />
</div>
</div>
</div>
</div>
<div class="box2">
<div class="box-header">
<div class="header-left"></div>
<div class="title">相关政策动态</div>
<div class="header-right">
<div class="icon">
<img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div>
<div class="box2-main">
<div class="box2-item" v-for="(item, index) in box2Data" :key="index">
<div class="box2-item-left">
<div class="point">
<img src="@/assets/images/dot.png" alt="" />
</div>
<div class="line" v-if="index < 5"></div>
</div>
<div class="box2-item-center">
<div class="title">{{ item.title }}</div>
<div class="content">{{ item.content }}</div>
</div>
<div class="box2-item-right">
<div class="time">{{ item.time }}</div>
<div class="img-box">
<img :src="item.img" alt="" />
</div>
</div>
</div>
</div>
<div class="box2-footer">
<div class="text">{{ "查看更多" }}</div>
<div class="icon">
<img src="@/assets/images/icon-double-down.png" alt="" />
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
// 政策建议落实情况
const box1Data = ref([
{
id: 1,
title: "示例标题1",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
},
{
id: 2,
title: "示例标题2",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
},
{
id: 3,
title: "示例标题3",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
},
{
id: 4,
title: "示例标题4",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
},
{
id: 5,
title: "示例标题5",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
},
{
id: 6,
title: "示例标题6",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
},
{
id: 7,
title: "示例标题7",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
},
{
id: 8,
title: "示例标题8",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
},
{
id: 9,
title: "示例标题9",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
},
{
id: 10,
title: "示例标题10",
tagList: ["人才交流", "移民政策"],
fileList: [
{
type: "法案",
name: "2024《重塑美国人口结构法案》"
},
{
type: "法案",
name: "2025《开放人才法案》"
}
]
}
]);
// 相关政策动态
const box2Data = ref([
{
title: "这是示例标题a",
content: "这是示例内容",
time: "2025-08-30",
img: 1
},
{
title: "这是示例标题a",
content: "这是示例内容",
time: "2025-08-30",
img: 1
},
{
title: "这是示例标题a",
content: "这是示例内容",
time: "2025-08-30",
img: 1
},
{
title: "这是示例标题a",
content: "这是示例内容",
time: "2025-08-30",
img: 1
},
{
title: "这是示例标题a",
content: "这是示例内容",
time: "2025-08-30",
img: 1
},
{
title: "这是示例标题a",
content: "这是示例内容",
time: "2025-08-30",
img: 1
}
]);
</script>
<style lang="scss" scoped>
.wrap {
display: flex;
justify-content: center;
gap: 16px;
.box-header {
width: 100%;
height: 50px;
display: flex;
position: relative;
.header-left {
margin-top: 18px;
width: 8px;
height: 20px;
border-radius: 0 4px 4px 0;
background: var(--color-main-active);
}
.title {
margin-left: 14px;
margin-top: 14px;
height: 26px;
line-height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
}
.header-btn-box {
position: absolute;
top: 15px;
right: 83px;
display: flex;
justify-content: flex-end;
gap: 8px;
.btn {
height: 28px;
padding: 0 8px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 28px;
}
.btnActive {
color: var(--color-main-active);
border: 1px solid var(--color-main-active);
}
}
.header-right {
position: absolute;
top: 14px;
right: 12px;
display: flex;
justify-content: flex-end;
gap: 4px;
.icon {
width: 28px;
height: 28px;
img {
width: 100%;
height: 100%;
}
}
}
}
.left {
height: 1442px;
.box1 {
margin-top: 16px;
width: 1104px;
height: 1405px;
margin-bottom: 16px;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.box1-main {
width: 1056px;
height: 1280px;
margin: 0 auto;
.box1-item {
height: 128px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
display: flex;
position: relative;
.left {
width: 28px;
height: 28px;
border-radius: 14px;
background: rgba(231, 243, 255, 1);
margin-left: 16px;
margin-top: 16px;
text-align: center;
line-height: 28px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
letter-spacing: 0px;
}
.center {
margin-left: 18px;
.title {
margin-top: 16px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
.tag-box {
display: flex;
margin-top: 7px;
gap: 8px;
.tag {
height: 22px;
padding: 0 8px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(247, 248, 249, 1);
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
letter-spacing: 0px;
text-align: left;
}
}
.file-box {
margin-top: 7px;
display: flex;
gap: 8px;
.file-item {
height: 32px;
padding: 0 8px;
border-radius: 4px;
background: rgba(246, 250, 255, 1);
display: flex;
align-items: center;
.file-item-left {
height: 22px;
padding: 0 4px;
border-radius: 4px;
background: rgba(231, 243, 255, 1);
line-height: 22px;
text-align: center;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
letter-spacing: 0px;
text-align: left;
}
.file-item-center {
margin-left: 12px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
.file-item-right {
margin-left: 12px;
width: 20px;
height: 20px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
.right {
position: absolute;
top: 16px;
right: 11px;
display: flex;
height: 24px;
justify-content: flex-end;
align-items: center;
gap: 9px;
.text {
height: 24px;
font-family: Microsoft YaHei;
font-size: 16px;
color: var(--color-main-active);
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: right;
}
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
.box1-footer {
height: 50px;
display: flex;
justify-content: space-between;
box-sizing: border-box;
padding: 20px;
.info {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
}
}
}
}
.box2 {
margin-top: 16px;
width: 480px;
height: 790px;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.box2-main {
margin: 0 auto;
margin-top: 15px;
width: 459px;
height: 654px;
.box2-item {
height: 109px;
display: flex;
.box2-item-left {
.point {
margin-left: 14px;
width: 10px;
height: 10px;
img {
width: 100%;
height: 100%;
}
}
.line {
width: 2px;
height: 109px;
background: #ccc;
margin-left: 18px;
}
}
.box2-item-center {
margin-left: 11px;
.title {
width: 314px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.content {
width: 314px;
height: 48px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: justify;
overflow: hidden;
}
}
.box2-item-right {
margin-left: 18px;
.time {
height: 22px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: right;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.img-box {
margin-top: 14px;
width: 78px;
height: 50px;
border-radius: 2px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
.box2-footer {
margin: 10px auto;
width: 108px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
cursor: pointer;
&:hover {
background: var(--color-bg-hover);
}
.text {
color: var(--color-main-active);
height: 22px;
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
}
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
</style>
\ No newline at end of file
...@@ -15,10 +15,7 @@ ...@@ -15,10 +15,7 @@
</div> </div>
</div> </div>
<div class="box1-main"> <div class="box1-main">
{{ {{ box1Data }}
`包括经济竞争在内的美中竞争自2017年以来一直在定义美国外交政策。这两个经济体是世界上第一和第二大国家经济体,并且深深交织在一起。改变关系,无论多么必要,可能是昂贵的。因此,美国面临着一项挑战,确保其经济在耦合的战略竞争条件下满足国家的需求。
为了应对这一挑战,兰德大学的研究人员对美中竞争进行了经济和制度分析,进行了参与式的远见练习,以了解确保美国经济健康的长期路径,并创建了两个经济竞争游戏,探索多个国家在相互交流的同时确保经济健康的动态...`
}}
</div> </div>
<div class="box1-footer"> <div class="box1-footer">
<div class="text">{{ "查看更多" }}</div> <div class="text">{{ "查看更多" }}</div>
...@@ -42,7 +39,15 @@ ...@@ -42,7 +39,15 @@
</div> </div>
<div class="box2-main"> <div class="box2-main">
<div class="box2-main-tag-box"> <div class="box2-main-tag-box">
<div class="tag" v-for="(item, index) in areaList" :key="index">{{ item }}</div> <div
class="tag"
:class="{ tagActive: activeArea === item }"
v-for="(item, index) in areaList"
:key="index"
@click="handleClickArea(item)"
>
{{ item }}
</div>
</div> </div>
<div class="box2-content" id="box2Chart"></div> <div class="box2-content" id="box2Chart"></div>
</div> </div>
...@@ -70,6 +75,35 @@ ...@@ -70,6 +75,35 @@
</div> </div>
</div> </div>
</div> </div>
<div class="box3-main">
<div class="box3-main-main">
<div class="box3-item" v-for="(item, index) in majorOpinions" :key="index">
<div class="left">
{{ item.id }}
</div>
<div class="center">
<div class="title">{{ item.title }}</div>
<div class="desc">{{ item.desc }}</div>
</div>
<div class="right">
<div class="tag" v-for="(val, idx) in item.tagList" :key="idx">
{{ val.name }}
</div>
</div>
<div class="more">
<img src="@/assets/icons/open.png" alt="" />
</div>
</div>
</div>
<div class="box3-main-footer">
<div class="info">
{{ `共105项调查` }}
</div>
<div class="page-box">
<el-pagination :page-size="10" background layout="prev, pager, next" :total="120" />
</div>
</div>
</div>
<div class="box3-footer"> <div class="box3-footer">
<div class="footer-left"> <div class="footer-left">
<img src="@/assets/icons/box-footer-left-icon.png" alt="" /> <img src="@/assets/icons/box-footer-left-icon.png" alt="" />
...@@ -90,8 +124,201 @@ ...@@ -90,8 +124,201 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import setChart from "@/utils/setChart";
import getWordCloudChart from "./utils/worldCloudChart";
// 内容摘要
const box1Data =
ref(`包括经济竞争在内的美中竞争自2017年以来一直在定义美国外交政策。这两个经济体是世界上第一和第二大国家经济体,并且深深交织在一起。改变关系,无论多么必要,可能是昂贵的。因此,美国面临着一项挑战,确保其经济在耦合的战略竞争条件下满足国家的需求。
为了应对这一挑战,兰德大学的研究人员对美中竞争进行了经济和制度分析,进行了参与式的远见练习,以了解确保美国经济健康的长期路径,并创建了两个经济竞争游戏,探索多个国家在相互交流的同时确保经济健康的动态...`);
// 涉及科技领域
const areaList = ref(["人工智能", "半导体与高科技", "经济与贸易", "地缘政治", "军事与安全", "国际规则与多边体系"]); const areaList = ref(["人工智能", "半导体与高科技", "经济与贸易", "地缘政治", "军事与安全", "国际规则与多边体系"]);
const activeArea = ref("人工智能");
const handleClickArea = area => {
activeArea.value = area;
};
const box2Data = ref([
{
name: "通用人工智能",
value: 100
},
{
name: "AI芯片",
value: 66
},
{
name: "计算能力又是",
value: 72
},
{
name: "基准测试",
value: 88
},
{
name: "出口管制",
value: 78
},
{
name: "军事AI",
value: 85
},
{
name: "生态系统",
value: 88
},
{
name: "模型能力",
value: 89
}
]);
// 主要观点
const majorOpinions = ref([
{
id: 1,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "关税",
status: 2
},
{
name: "跨境电商",
status: 1
}
]
},
{
id: 2,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "私有经济",
status: 2
}
]
},
{
id: 3,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "半导体",
status: 4
}
]
},
{
id: 4,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "关税",
status: 2
},
{
name: "跨境电商",
status: 1
}
]
},
{
id: 5,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "关税",
status: 2
},
{
name: "跨境电商",
status: 1
}
]
},
{
id: 6,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "关税",
status: 2
},
{
name: "跨境电商",
status: 1
}
]
},
{
id: 7,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "产业脱钩",
status: 6
}
]
},
{
id: 8,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "关税",
status: 2
},
{
name: "跨境电商",
status: 1
}
]
},
{
id: 9,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "关税",
status: 2
},
{
name: "跨境电商",
status: 1
}
]
},
{
id: 10,
title: "我是示例标题",
desc: "我是示例内容",
tagList: [
{
name: "关税",
status: 2
},
{
name: "跨境电商",
status: 1
}
]
}
]);
onMounted(() => {
const box2Chart = getWordCloudChart(box2Data.value);
setChart(box2Chart, "box2Chart");
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -237,11 +464,18 @@ const areaList = ref(["人工智能", "半导体与高科技", "经济与贸易" ...@@ -237,11 +464,18 @@ const areaList = ref(["人工智能", "半导体与高科技", "经济与贸易"
gap: 8px; gap: 8px;
.tag { .tag {
height: 28px; height: 28px;
line-height: 28px;
padding: 0 8px; padding: 0 8px;
box-sizing: border-box; box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1); border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px; border-radius: 4px;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
cursor: pointer;
}
.tagActive {
color: var(--color-main-active);
border: 1px solid var(--color-main-active);
background: rgba(231, 243, 255, 1);
} }
} }
.box2-content { .box2-content {
...@@ -259,12 +493,124 @@ const areaList = ref(["人工智能", "半导体与高科技", "经济与贸易" ...@@ -259,12 +493,124 @@ const areaList = ref(["人工智能", "半导体与高科技", "经济与贸易"
margin-top: 17px; margin-top: 17px;
.box3 { .box3 {
width: 1103px; width: 1103px;
height: 936px; height: 946px;
border: 1px solid rgba(234, 236, 238, 1); border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px; border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1); box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
position: relative; position: relative;
.box3-main {
width: 1057px;
height: 800px;
margin: 0 auto;
.box3-main-main {
height: 720px;
overflow: hidden;
.box3-item {
width: 1057px;
height: 72px;
box-sizing: border-box;
border-radius: 4px;
display: flex;
position: relative;
.left {
margin-top: 24px;
margin-left: 15px;
width: 24px;
height: 24px;
border-radius: 12px;
line-height: 24px;
text-align: center;
background: rgba(231, 243, 255, 1);
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 12px;
font-weight: 400;
letter-spacing: 0px;
}
.center {
width: 770px;
margin-left: 13px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.title {
margin-top: 12px;
height: 26px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px;
text-align: left;
}
.desc {
height: 22px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
}
}
.right {
margin-top: 26px;
width: 180px;
height: 22px;
display: flex;
gap: 8px;
justify-content: flex-end;
.tag {
height: 22px;
padding: 0 8px;
box-sizing: border-box;
border: 1px solid rgba(217, 247, 190, 1);
border-radius: 4px;
background: rgba(246, 255, 237, 1);
color: rgba(82, 196, 26, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
}
.more {
width: 16px;
height: 16px;
position: absolute;
top: 28px;
right: 20px;
img {
width: 100%;
height: 100%;
}
}
}
.box3-item:nth-child(2n-1) {
border-bottom: 1px solid rgba(234, 236, 238, 1);
border-top: 1px solid rgba(234, 236, 238, 1);
background: rgba(247, 248, 249, 1);
}
}
.box3-main-footer {
height: 80px;
display: flex;
justify-content: space-between;
padding: 30px 5px;
.info {
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
}
}
}
.box3-footer { .box3-footer {
position: absolute; position: absolute;
left: 22px; left: 22px;
......
const getWordCloudChart = (data) => {
const option = {
grid: {
left: 0,
top: 0,
right: 0,
bottom: 0,
},
series: [
{
type: "wordCloud",
shape: "circle", //
// 其他形状你可以使用形状路径
// 或者自定义路径
// shape: 'circle' // 圆形(默认)
// shape: 'rect' // 矩形
// shape: 'roundRect' // 圆角矩形
// shape: 'triangle' // 三角形
// shape: 'diamond' // 菱形
// shape: 'pentagon' // 五边形
// shape: 'star' // 星形
// shape: 'cardioid' // 心形
gridSize: 30, // 网格大小,影响词间距。
sizeRange: [10, 25], // 定义词云中文字大小的范围
rotationRange: [0, 0],
rotationStep: 15,
drawOutOfBound: false, // 是否超出画布
// 字体
textStyle: {
// normal: {
// color: function () {
// return 'rgb(' + [
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160)
// ].join(',') + ')';
// }
// },
color: function () {
let colors = [
"rgba(189, 33, 33, 1)",
"rgba(232, 151, 21, 1)",
"rgba(220, 190, 68, 1)",
"rgba(96, 58, 186, 1)",
"rgba(32, 121, 69, 1)",
"rgba(22, 119, 255, 1)",
];
return colors[parseInt(Math.random() * colors.length)];
},
emphasis: {
shadowBlur: 5,
shadowColor: "#333",
},
},
// 设置词云数据
data: data,
},
],
}
return option
}
export default getWordCloudChart
\ No newline at end of file
...@@ -157,6 +157,7 @@ import Img2 from "./images/img2.png"; ...@@ -157,6 +157,7 @@ import Img2 from "./images/img2.png";
import Img3 from "./images/img3.png"; import Img3 from "./images/img3.png";
import Img4 from "./images/img4.png"; import Img4 from "./images/img4.png";
// 提出建议领域分布
const box1Data = ref([ const box1Data = ref([
{ {
name: "半导体", name: "半导体",
...@@ -211,6 +212,7 @@ const box1YearList = ref([ ...@@ -211,6 +212,7 @@ const box1YearList = ref([
} }
]); ]);
// 相关政策领域分布
const box2Data = ref([ const box2Data = ref([
{ {
name: "集成电路", name: "集成电路",
...@@ -272,6 +274,7 @@ const box2YearList = ref([ ...@@ -272,6 +274,7 @@ const box2YearList = ref([
} }
]); ]);
// 热门研究方向变化趋势
const box3Data = ref({ const box3Data = ref({
title: ["2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"], title: ["2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
data: [ data: [
...@@ -306,6 +309,7 @@ const box3YearList = ref([ ...@@ -306,6 +309,7 @@ const box3YearList = ref([
} }
]); ]);
// 搜索政策建议
const searchPolicy = ref(""); const searchPolicy = ref("");
const yearList = ref([ const yearList = ref([
...@@ -325,6 +329,7 @@ const yearList = ref([ ...@@ -325,6 +329,7 @@ const yearList = ref([
const selectedYear = ref("近一年发布"); const selectedYear = ref("近一年发布");
// 科技领域
const areaList = ref(["人工智能", "半导体/芯片", "能源与气候", "国际关系", "经济政策", "国防与安全"]); const areaList = ref(["人工智能", "半导体/芯片", "能源与气候", "国际关系", "经济政策", "国防与安全"]);
const selectedAreaList = ref(["人工智能", "半导体/芯片"]); const selectedAreaList = ref(["人工智能", "半导体/芯片"]);
...@@ -686,12 +691,12 @@ onMounted(() => { ...@@ -686,12 +691,12 @@ onMounted(() => {
border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0;
} }
.title { .title {
height: 24px; height: 26px;
color: var(--color-main-active); color: var(--color-main-active);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 20px; font-size: 20px;
font-weight: 700; font-weight: 700;
line-height: 24px; line-height: 26px;
letter-spacing: 1px; letter-spacing: 1px;
text-align: left; text-align: left;
} }
......
...@@ -18,18 +18,18 @@ ...@@ -18,18 +18,18 @@
<div class="select-box"> <div class="select-box">
<div class="select-box-header"> <div class="select-box-header">
<div class="icon"></div> <div class="icon"></div>
<div class="title">{{ "地区筛选" }}</div> <div class="title">{{ "报告类型" }}</div>
</div> </div>
<div class="select-main"> <div class="select-main">
<div class="checkbox-group"> <div class="checkbox-group">
<el-checkbox <el-checkbox
v-for="region in filters.regions" v-for="type in reportTypeList"
:key="region.id" :key="type.id"
v-model="activeFilters.regions" v-model="selectedReportTypeList"
:label="region.id" :label="type.id"
class="filter-checkbox" class="filter-checkbox"
> >
{{ region.name }} {{ type.name }}
</el-checkbox> </el-checkbox>
</div> </div>
</div> </div>
...@@ -37,14 +37,14 @@ ...@@ -37,14 +37,14 @@
<div class="select-box"> <div class="select-box">
<div class="select-box-header"> <div class="select-box-header">
<div class="icon"></div> <div class="icon"></div>
<div class="title">{{ "智库类型" }}</div> <div class="title">{{ "研究类型" }}</div>
</div> </div>
<div class="select-main select-main1"> <div class="select-main">
<div class="checkbox-group"> <div class="checkbox-group">
<el-checkbox <el-checkbox
v-for="type in filters.types" v-for="type in researchTypeList"
:key="type.id" :key="type.id"
v-model="activeFilters.types" v-model="selectedResearchTypeList"
:label="type.id" :label="type.id"
class="filter-checkbox" class="filter-checkbox"
> >
...@@ -53,29 +53,19 @@ ...@@ -53,29 +53,19 @@
</div> </div>
</div> </div>
</div> </div>
<div class="select-box"> <div class="select-box">
<div class="select-box-header"> <div class="select-box-header">
<div class="icon"></div> <div class="icon"></div>
<div class="title">{{ "研究领域" }}</div> <div class="title">{{ "作者" }}</div>
</div> </div>
<div class="select-main"> <div class="input-main">
<div class="checkbox-group"> <el-input placeholder="输入作者名字" v-model="author" />
<el-checkbox
v-for="research in filters.researches"
:key="research.id"
v-model="activeFilters.researches"
:label="research.id"
class="filter-checkbox"
>
{{ research.name }}
</el-checkbox>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="right"> <div class="right">
<div class="card-box"> <div class="card-box">
<div class="footer-card" v-for="(item, index) in curFooterList" :key="index"> <div class="footer-card" v-for="(item, index) in curFooterList" :key="index" @click="handleToReportDetail()">
<div class="footer-card-top"> <div class="footer-card-top">
<img :src="item.img" alt="" /> <img :src="item.img" alt="" />
</div> </div>
...@@ -103,6 +93,7 @@ ...@@ -103,6 +93,7 @@
<script setup> <script setup>
import { ref, reactive, onMounted } from "vue"; import { ref, reactive, onMounted } from "vue";
import router from "@/router";
import Img1 from "./images/img1.png"; import Img1 from "./images/img1.png";
import Img2 from "./images/img2.png"; import Img2 from "./images/img2.png";
import Img3 from "./images/img3.png"; import Img3 from "./images/img3.png";
...@@ -116,61 +107,57 @@ import Img10 from "./images/img10.png"; ...@@ -116,61 +107,57 @@ import Img10 from "./images/img10.png";
import Img11 from "./images/img11.png"; import Img11 from "./images/img11.png";
import Img12 from "./images/img12.png"; import Img12 from "./images/img12.png";
const activeFilters = reactive({ const handleToReportDetail = () => {
regions: ["north_america"], const route = router.resolve({
types: ["gov"], name: 'ReportDetail',
researches: ["全部领域"] params: {
}); id: 1
}
});
window.open(route.href, "_blank");
}
const reportTypeList = ref([
{
id: '研究报告',
name: '研究报告',
},
{
id: '简报',
name: '简报',
},
{
id: '会议记录',
name: '会议记录',
},
{
id: '期刊文章',
name: '期刊文章',
},
])
const selectedReportTypeList = ref(['研究报告'])
const filters = reactive({ const researchTypeList = ref([
regions: [ {
{ id: "north_america", name: "北美" }, id: '研究报告',
{ id: "europe", name: "欧洲" }, name: '研究报告',
{ id: "asia", name: "亚洲" }, },
{ id: "other", name: "其他地区" } {
], id: '简报',
types: [ name: '简报',
{ id: "gov", name: "政府背景" }, },
{ id: "university", name: "高校附属" }, {
{ id: "independent", name: "独立智库" }, id: '会议记录',
{ id: "corporate", name: "企业视景" } name: '会议记录',
], },
researches: [ {
{ id: '期刊文章',
id: "全部领域", name: '期刊文章',
name: "全部领域" },
}, ])
{ const selectedResearchTypeList = ref(['研究报告'])
id: "人工智能",
name: "人工智能"
},
{
id: "通信网络",
name: "通信网络"
},
{
id: "量子科技",
name: "量子科技"
},
{
id: "能源",
name: "能源"
},
{
id: "生物技术",
name: "生物技术"
},
{ const author = ref('') // 作者
id: "新材料",
name: "新材料"
},
{
id: "海洋",
name: "海洋"
}
]
});
const curFooterList = ref([ const curFooterList = ref([
{ {
...@@ -263,7 +250,6 @@ const yearList = ref([ ...@@ -263,7 +250,6 @@ const yearList = ref([
]); ]);
const selectedYear = ref("近一年发布"); const selectedYear = ref("近一年发布");
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -301,7 +287,7 @@ const selectedYear = ref("近一年发布"); ...@@ -301,7 +287,7 @@ const selectedYear = ref("近一年发布");
gap: 16px; gap: 16px;
.left { .left {
width: 300px; width: 300px;
height: 806px; height: 520px;
box-sizing: border-box; box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1); border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px; border-radius: 10px;
...@@ -321,12 +307,12 @@ const selectedYear = ref("近一年发布"); ...@@ -321,12 +307,12 @@ const selectedYear = ref("近一年发布");
border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0;
} }
.title { .title {
height: 24px; height: 26px;
color: var(--color-main-active); color: var(--color-main-active);
font-family: Microsoft YaHei; font-family: Microsoft YaHei;
font-size: 16px; font-size: 20px;
font-weight: 700; font-weight: 700;
line-height: 24px; line-height: 26px;
letter-spacing: 1px; letter-spacing: 1px;
text-align: left; text-align: left;
} }
...@@ -337,6 +323,13 @@ const selectedYear = ref("近一年发布"); ...@@ -337,6 +323,13 @@ const selectedYear = ref("近一年发布");
.select-main1 { .select-main1 {
width: 100px; width: 100px;
} }
.input-main{
margin: 10px auto;
width: 250px;
height: 34px;
border-radius: 10px;
border: 1px solid rgba(230, 231, 232, 1);
}
} }
} }
.right { .right {
...@@ -354,6 +347,12 @@ const selectedYear = ref("近一年发布"); ...@@ -354,6 +347,12 @@ const selectedYear = ref("近一年发布");
border-radius: 10px; border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1); box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
&:hover {
transform: translateY(-3px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
cursor: pointer;
.footer-card-top { .footer-card-top {
width: 384px; width: 384px;
height: 206px; height: 206px;
...@@ -407,4 +406,8 @@ const selectedYear = ref("近一年发布"); ...@@ -407,4 +406,8 @@ const selectedYear = ref("近一年发布");
} }
} }
} }
.filter-checkbox {
width: 180px;
}
</style> </style>
\ No newline at end of file
...@@ -189,6 +189,7 @@ import Icon3 from "./images/icon3.png"; ...@@ -189,6 +189,7 @@ import Icon3 from "./images/icon3.png";
import Icon4 from "./images/icon4.png"; import Icon4 from "./images/icon4.png";
import Icon5 from "./images/icon5.png"; import Icon5 from "./images/icon5.png";
// 基本信息
const basicInfo = ref({ const basicInfo = ref({
img: InfoImg, img: InfoImg,
country: "美国", country: "美国",
...@@ -198,7 +199,7 @@ const basicInfo = ref({ ...@@ -198,7 +199,7 @@ const basicInfo = ref({
num: "约1,700名员工 ", num: "约1,700名员工 ",
money: "约3.5亿美元 " money: "约3.5亿美元 "
}); });
// 全球分支机构
const worldInfo = ref({ const worldInfo = ref({
position1: "圣莫尼卡(总部)、华盛顿特区、匹兹堡、波士顿", position1: "圣莫尼卡(总部)、华盛顿特区、匹兹堡、波士顿",
position2: "英国剑桥、比利时布鲁塞尔", position2: "英国剑桥、比利时布鲁塞尔",
...@@ -206,6 +207,7 @@ const worldInfo = ref({ ...@@ -206,6 +207,7 @@ const worldInfo = ref({
position4: "堪培拉 " position4: "堪培拉 "
}); });
// 经费来源
const box1LeftData = ref({ const box1LeftData = ref({
total: "4.358亿美元", total: "4.358亿美元",
gov: "3.271亿美元", gov: "3.271亿美元",
...@@ -250,6 +252,7 @@ const box1ChartData = ref([ ...@@ -250,6 +252,7 @@ const box1ChartData = ref([
} }
]); ]);
// 研究领域演变
const timeLineList = ref([ const timeLineList = ref([
{ {
time: "2025年7月25日", time: "2025年7月25日",
...@@ -273,39 +276,8 @@ const timeLineList = ref([ ...@@ -273,39 +276,8 @@ const timeLineList = ref([
} }
]); ]);
const box3RightData = ref([
{
img: Icon1,
name: "杰森·马西尼 ​",
postion: "兰德公司总裁兼首席执行官",
desc: "曾任职于哈佛大学经济学院、美国财政部"
},
{
img: Icon2,
name: "安德鲁·R·霍恩 ​",
postion: "高级副总裁,研究与分析",
desc: "曾任职于白宫科技政策顾问办公室"
},
{
img: Icon3,
name: "杰森·马西尼 ​",
postion: "兰德公司总裁兼首席执行官",
desc: "日籍研究院,毕业于斯坦福大学"
},
{
img: Icon4,
name: "梅丽莎·罗 ​",
postion: "副总裁,全球研究人才",
desc: "曾任职于美国国防部"
},
{
img: Icon5,
name: "安妮塔·钱德拉 ​ ​",
postion: "副总裁兼主任,兰德社会和经济福祉",
desc: "曾任职于哈佛大学经济学院、美国商务部"
}
]);
// 核心研究人员
const handleBox3Chart = () => { const handleBox3Chart = () => {
// 将分类数据转换为树状图格式 // 将分类数据转换为树状图格式
const treemapData = []; const treemapData = [];
...@@ -356,6 +328,39 @@ const handleBox3Chart = () => { ...@@ -356,6 +328,39 @@ const handleBox3Chart = () => {
setChart(box3Chart, "box3Chart"); setChart(box3Chart, "box3Chart");
}; };
const box3RightData = ref([
{
img: Icon1,
name: "杰森·马西尼 ​",
postion: "兰德公司总裁兼首席执行官",
desc: "曾任职于哈佛大学经济学院、美国财政部"
},
{
img: Icon2,
name: "安德鲁·R·霍恩 ​",
postion: "高级副总裁,研究与分析",
desc: "曾任职于白宫科技政策顾问办公室"
},
{
img: Icon3,
name: "杰森·马西尼 ​",
postion: "兰德公司总裁兼首席执行官",
desc: "日籍研究院,毕业于斯坦福大学"
},
{
img: Icon4,
name: "梅丽莎·罗 ​",
postion: "副总裁,全球研究人才",
desc: "曾任职于美国国防部"
},
{
img: Icon5,
name: "安妮塔·钱德拉 ​ ​",
postion: "副总裁兼主任,兰德社会和经济福祉",
desc: "曾任职于哈佛大学经济学院、美国商务部"
}
]);
onMounted(() => { onMounted(() => {
const box1Chart = getPieChart(box1ChartData.value); const box1Chart = getPieChart(box1ChartData.value);
setChart(box1Chart, "box1Chart"); setChart(box1Chart, "box1Chart");
......
<template>
<div class="dashboard-container">
<div class="top-row">
<el-card class="chart-card" shadow="hover">
<template #header>
<div class="card-header">
<div class="title">
<el-icon color="#409EFF"><TrendCharts /></el-icon>
<span>政策建议趋势分布</span>
</div>
<el-select v-model="lineChartPeriod" size="small" style="width: 100px">
<el-option label="近十年" value="10years" />
<el-option label="近五年" value="5years" />
</el-select>
</div>
</template>
<div ref="lineChartRef" class="chart-container"></div>
</el-card>
<el-card class="chart-card" shadow="hover">
<template #header>
<div class="card-header">
<div class="title">
<el-icon color="#409EFF"><PieChart /></el-icon>
<span>政策建议领域分布</span>
</div>
<el-select v-model="pieChartYear" size="small" style="width: 100px">
<el-option label="2025年" value="2025" />
<el-option label="2024年" value="2024" />
</el-select>
</div>
</template>
<div ref="pieChartRef" class="chart-container"></div>
</el-card>
</div>
<div class="bottom-row">
<el-card class="chart-card" shadow="hover">
<template #header>
<div class="card-header">
<div class="title">
<el-icon color="#409EFF"><Share /></el-icon>
<span>智库资金流向</span>
</div>
</div>
</template>
<div ref="sankeyChartRef" class="chart-container"></div>
</el-card>
<el-card class="chart-card" shadow="hover">
<template #header>
<div class="card-header">
<div class="title">
<el-icon color="#409EFF"><Opportunity /></el-icon>
<span>智库研究热点</span>
</div>
<el-select v-model="hotspotPeriod" size="small" style="width: 100px">
<el-option label="近一年" value="1year" />
<el-option label="近半年" value="halfyear" />
</el-select>
</div>
</template>
<div class="list-container">
<div v-for="(item, index) in hotspotList" :key="index" class="list-item">
<div class="rank-wrapper">
<span :class="['rank-num', index < 3 ? 'top-rank' : 'normal-rank']">
{{ index + 1 }}
</span>
</div>
<div class="content-text" :title="item.title">{{ item.title }}</div>
<div class="report-count">{{ item.count }}份报告 ></div>
</div>
</div>
</el-card>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import {
TrendCharts,
PieChart,
Share,
Opportunity
} from '@element-plus/icons-vue';
// --- 状态管理 ---
const lineChartPeriod = ref('10years');
const pieChartYear = ref('2025');
const hotspotPeriod = ref('1year');
// --- DOM 引用 ---
const lineChartRef = ref(null);
const pieChartRef = ref(null);
const sankeyChartRef = ref(null);
// --- 模拟数据 ---
// 列表数据
const hotspotList = ref([
{ title: '人工智能领域竞争发展', count: 11 },
{ title: '美元未来与能源出口挂钩', count: 7 },
{ title: '量子领域国家合作', count: 5 },
{ title: '限制中国产燃油进口', count: 5 },
{ title: '禁止政府部门采购受控半导体或服务', count: 4 },
{ title: '禁止向部分中国实体提供资金', count: 3 },
{ title: '中国生产电池', count: 3 },
{ title: '重视新兴中国技术公司威胁', count: 2 },
{ title: '禁止卫星出口至中国', count: 1 },
{ title: '华为设备', count: 1 },
]);
// ECharts 实例
let lineChart = null;
let pieChart = null;
let sankeyChart = null;
// --- 初始化图表 ---
const initLineChart = () => {
if (!lineChartRef.value) return;
lineChart = echarts.init(lineChartRef.value);
const option = {
color: ['#409EFF', '#67C23A', '#909399', '#E6A23C', '#73C0DE', '#F56C6C'],
tooltip: { trigger: 'axis' },
legend: {
data: ['人工智能', '集成电路', '量子科技', '生物科技', '通信网络', '能源'],
bottom: 'top',
icon: 'circle'
},
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
xAxis: {
type: 'category',
boundaryGap: false,
data: ['2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022', '2023', '2024', '2025']
},
yAxis: { type: 'value' },
series: [
{ name: '人工智能', type: 'line', smooth: true, areaStyle: { opacity: 0.1 }, data: [150, 80, 90, 100, 80, 100, 130, 150, 140, 170, 190, 175] },
{ name: '集成电路', type: 'line', smooth: true, areaStyle: { opacity: 0.1 }, data: [70, 100, 125, 115, 135, 150, 168, 165, 165, 172, 172, 185] },
{ name: '量子科技', type: 'line', smooth: true, data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 10] }, // 模拟低数据
{ name: '生物科技', type: 'line', smooth: true, data: [10, 5, 5, 10, 10, 15, 20, 30, 28, 30, 45, 45] },
{ name: '通信网络', type: 'line', smooth: true, areaStyle: { opacity: 0.1 }, data: [40, 35, 45, 50, 50, 48, 55, 75, 65, 65, 68, 60] },
{ name: '能源', type: 'line', smooth: true, areaStyle: { opacity: 0.1 }, data: [100, 75, 65, 85, 65, 75, 85, 120, 118, 150, 140, 110] },
]
};
lineChart.setOption(option);
};
const initPieChart = () => {
if (!pieChartRef.value) return;
pieChart = echarts.init(pieChartRef.value);
const option = {
tooltip: { trigger: 'item' },
legend: {
orient: 'vertical',
left: '5%',
top: 'center',
itemGap: 20,
formatter: (name) => {
// 简单的 mock 数据映射,实际应从 data 动态获取
const dataMap = {
'人工智能': '50项 21%',
'集成电路': '46项 18%',
'通信网络': '40项 16%',
'能源': '32项 14%',
'量子科技': '31项 12%',
'生物科技': '30项 11%',
'其他': '24项 8%'
};
return `{name|${name}}\n{val|${dataMap[name]}}`;
},
textStyle: {
rich: {
name: { fontWeight: 'bold', fontSize: 14, padding: [0, 0, 5, 0] },
val: { color: '#666', fontSize: 12 }
}
}
},
series: [
{
name: '领域分布',
type: 'pie',
radius: ['45%', '70%'],
center: ['65%', '50%'], // 向右偏移,留位置给 Legend
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2
},
label: { show: false }, // 隐藏连接线上的标签,使用 Legend
data: [
{ value: 50, name: '人工智能', itemStyle: { color: '#409EFF' } },
{ value: 46, name: '集成电路', itemStyle: { color: '#F56C6C' } },
{ value: 40, name: '通信网络', itemStyle: { color: '#a0cfff' } },
{ value: 32, name: '能源', itemStyle: { color: '#E6A23C' } },
{ value: 31, name: '量子科技', itemStyle: { color: '#cceeff' } },
{ value: 30, name: '生物科技', itemStyle: { color: '#d1bdf2' } },
{ value: 24, name: '其他', itemStyle: { color: '#f2f2f2' } }
]
}
]
};
pieChart.setOption(option);
};
const initSankeyChart = () => {
if (!sankeyChartRef.value) return;
sankeyChart = echarts.init(sankeyChartRef.value);
// 简化的桑基图节点和连接
const nodes = [
{ name: '美国', itemStyle: { color: '#1f5cb8' } },
{ name: '英国', itemStyle: { color: '#6f42c1' } },
{ name: '加拿大', itemStyle: { color: '#d9534f' } },
// 中间层
{ name: '美国能源部', itemStyle: { color: '#a4c639' } },
{ name: '美国财政部', itemStyle: { color: '#f06292' } },
{ name: '美国国务院', itemStyle: { color: '#b08d55' } },
{ name: '美国国际开发署', itemStyle: { color: '#4285f4' } },
{ name: '美国内政部', itemStyle: { color: '#8cae9e' } },
{ name: '美国国家民主基金会', itemStyle: { color: '#a1887f' } },
// 右侧层 (部分)
{ name: '麻省理工学院科技评论', itemStyle: { color: '#7cb342' } },
{ name: '麦肯锡全球研究院', itemStyle: { color: '#cddc39' } },
{ name: '卡内基国际和平研究院', itemStyle: { color: '#afb42b' } },
{ name: '战略与国际研究中心', itemStyle: { color: '#827717' } },
{ name: '兰德公司', itemStyle: { color: '#689f38' } },
];
const links = [
{ source: '美国', target: '美国能源部', value: 50 },
{ source: '美国', target: '美国财政部', value: 40 },
{ source: '美国', target: '美国国务院', value: 60 },
{ source: '美国', target: '美国国际开发署', value: 20 },
{ source: '美国', target: '美国内政部', value: 15 },
{ source: '英国', target: '美国国务院', value: 10 },
{ source: '加拿大', target: '美国能源部', value: 5 },
// Flow to right
{ source: '美国能源部', target: '麻省理工学院科技评论', value: 20 },
{ source: '美国能源部', target: '麦肯锡全球研究院', value: 25 },
{ source: '美国财政部', target: '卡内基国际和平研究院', value: 30 },
{ source: '美国国务院', target: '战略与国际研究中心', value: 40 },
{ source: '美国国务院', target: '兰德公司', value: 15 },
];
const option = {
tooltip: { trigger: 'item', triggerOn: 'mousemove' },
series: [
{
type: 'sankey',
layout: 'none',
emphasis: { focus: 'adjacency' },
nodeAlign: 'left',
data: nodes,
links: links,
lineStyle: { color: 'gradient', curveness: 0.5, opacity: 0.3 },
label: { position: 'right', color: '#666', fontSize: 10 }
}
]
};
sankeyChart.setOption(option);
};
// --- 生命周期钩子 ---
onMounted(() => {
nextTick(() => {
initLineChart();
initPieChart();
initSankeyChart();
});
window.addEventListener('resize', handleResize);
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
lineChart?.dispose();
pieChart?.dispose();
sankeyChart?.dispose();
});
const handleResize = () => {
lineChart?.resize();
pieChart?.resize();
sankeyChart?.resize();
};
</script>
<style scoped>
.dashboard-container {
background-color: #f5f7fa;
padding: 20px;
display: flex;
flex-direction: column;
gap: 20px;
height: 100vh; /* 或根据需要调整高度 */
box-sizing: border-box;
}
/* 通用布局类 */
.top-row, .bottom-row {
display: grid;
grid-template-columns: 1.5fr 1fr; /* 2列等宽 */
gap: 20px;
flex: 1; /* 上下平分高度 */
min-height: 0; /* 防止溢出 */
}
.chart-card {
display: flex;
flex-direction: column;
height: 100%;
border-radius: 8px;
}
/* Element Plus Card 样式覆盖 */
:deep(.el-card__header) {
padding: 15px 20px;
border-bottom: 1px solid #ebeef5;
}
:deep(.el-card__body) {
flex: 1;
padding: 10px;
position: relative;
height: 0; /* 关键:配合 flex:1 让内部图表自适应高度 */
}
/* 头部样式 */
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.title {
display: flex;
align-items: center;
gap: 8px;
font-size: 16px;
font-weight: bold;
color: #303133;
}
/* 图表容器 */
.chart-container {
width: 100%;
height: 100%;
}
/* 列表样式 */
.list-container {
height: 100%;
overflow-y: auto;
padding: 0 10px;
}
.list-item {
display: flex;
align-items: center;
padding: 12px 0;
border-bottom: 1px dashed #eee;
font-size: 14px;
color: #606266;
}
.list-item:last-child {
border-bottom: none;
}
.rank-wrapper {
width: 30px;
text-align: center;
margin-right: 10px;
}
.rank-num {
font-weight: bold;
font-family: Arial, sans-serif;
}
.top-rank {
color: #E6A23C; /* 前三名金色 */
font-size: 16px;
}
.normal-rank {
color: #909399; /* 其他灰色 */
font-size: 14px;
}
.content-text {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #303133;
cursor: pointer;
}
.content-text:hover {
color: #409EFF;
}
.report-count {
color: #909399;
font-size: 12px;
margin-left: 10px;
}
/* 响应式调整 (可选) */
@media (max-width: 1024px) {
.top-row, .bottom-row {
grid-template-columns: 1fr; /* 小屏幕变为单列 */
}
.dashboard-container {
height: auto; /* 允许滚动 */
}
.chart-card {
height: 400px; /* 固定高度 */
}
}
</style>
\ No newline at end of file
<template>
<div class="dashboard-container">
<el-row :gutter="20">
<el-col :span="8" :xs="24">
<el-card shadow="hover" class="dashboard-card">
<template #header>
<div class="card-header">
<div class="title-group">
<el-icon class="icon-blue"><PieChart /></el-icon>
<span class="title">提出建议领域分布</span>
</div>
<span class="link">查看数据源 ></span>
</div>
</template>
<div class="card-body">
<div class="filter-row">
<el-select v-model="yearLeft" size="small" class="year-select">
<el-option label="2025年" value="2025" />
<el-option label="2024年" value="2024" />
</el-select>
</div>
<div ref="leftChartRef" class="chart-container"></div>
</div>
</el-card>
</el-col>
<el-col :span="8" :xs="24">
<el-card shadow="hover" class="dashboard-card">
<template #header>
<div class="card-header">
<div class="title-group">
<el-icon class="icon-orange"><Flag /></el-icon>
<span class="title">相关政策领域分布</span>
</div>
<span class="link">查看数据源 ></span>
</div>
</template>
<div class="card-body">
<div class="filter-row">
<el-select v-model="yearMiddle" size="small" class="year-select">
<el-option label="2025年" value="2025" />
<el-option label="2024年" value="2024" />
</el-select>
</div>
<div class="policy-list">
<div v-for="(item, index) in currentPolicyList" :key="index" class="policy-item">
<div class="item-label">
<span class="dot" :style="{ backgroundColor: item.color }"></span>
<span class="name">{{ item.name }}</span>
</div>
<div class="progress-track">
<div
class="progress-bar"
:style="{ width: item.percent + '%', backgroundColor: item.color }"
></div>
</div>
<div class="item-value">
<span class="count">{{ item.current }}项 / {{ item.total }}项</span>
<span class="percent">{{ item.percent }}%</span>
</div>
</div>
</div>
</div>
</el-card>
</el-col>
<el-col :span="8" :xs="24">
<el-card shadow="hover" class="dashboard-card">
<template #header>
<div class="card-header">
<div class="title-group">
<el-icon class="icon-orange"><TrendCharts /></el-icon>
<span class="title">热门研究方向变化趋势</span>
</div>
<span class="link">查看数据源 ></span>
</div>
</template>
<div class="card-body">
<div class="filter-row right-filter">
<el-select v-model="yearRight" size="small" class="year-select">
<el-option label="2025年" value="2025" />
<el-option label="2024年" value="2024" />
</el-select>
</div>
<div ref="rightChartRef" class="chart-container"></div>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick, watch, computed } from 'vue'
import { PieChart, Flag, TrendCharts } from '@element-plus/icons-vue'
import * as echarts from 'echarts'
// ==================== 1. 模拟数据源 (Mock Data) ====================
// 视觉颜色常量 (为了还原图片,不同图表用了不同色系)
const COLORS = {
pie: ['#409EFF', '#F56C6C', '#a0cfff', '#E6A23C', '#b3e19d', '#d1edc4', '#909399'],
line: {
ic: '#409EFF', // 集成电路
ai: '#67C23A', // 人工智能 (青绿)
comm: '#8e44ad', // 通信 (紫)
quantum: '#E6A23C', // 量子 (橙)
bio: '#a0cfff', // 生物 (淡蓝)
energy: '#F56C6C' // 能源 (红)
}
}
const mockDatabase = {
'2025': {
// 左侧环形图数据
pieData: [
{ value: 50, name: '集成电路' },
{ value: 46, name: '人工智能' },
{ value: 40, name: '通信网络' },
{ value: 32, name: '量子科技' },
{ value: 31, name: '生物科技' },
{ value: 30, name: '能源' },
{ value: 24, name: '其他' }
],
// 中间列表数据
policyData: [
{ name: '集成电路', current: 2, total: 10, percent: 20, color: '#c0392b' },
{ name: '人工智能', current: 1, total: 6, percent: 17, color: '#2e7d32' },
{ name: '通信网络', current: 2, total: 7, percent: 26, color: '#f39c12' },
{ name: '量子科技', current: 1, total: 2, percent: 50, color: '#c0392b' },
{ name: '生物科技', current: 3, total: 7, percent: 43, color: '#c0392b' },
{ name: '能源', current: 11, total: 20, percent: 55, color: '#c0392b' }
],
// 右侧折线图数据
lineData: {
xAxis: ['2023\nQ1', '2023\nQ3', '2024\nQ1', '2024\nQ3', '2025\nQ1', '2025\nQ3'],
series: {
'集成电路': [32, 13, 20, 28, 37, 40],
'量子科技': [29, 18, 15, 19, 14, 9],
'生物科技': [15, 17, 24, 23, 16, 24],
'能源': [20, 22, 12, 14, 19, 5],
'通信网络': [3, 3, 1, 6, 4, 2],
'人工智能': [5, 15, 25, 10, 15, 18]
}
}
},
'2024': {
pieData: [
{ value: 40, name: '集成电路' },
{ value: 35, name: '人工智能' },
{ value: 45, name: '通信网络' },
{ value: 20, name: '量子科技' },
{ value: 25, name: '生物科技' },
{ value: 35, name: '能源' },
{ value: 15, name: '其他' }
],
policyData: [
{ name: '集成电路', current: 5, total: 8, percent: 62, color: '#c0392b' },
{ name: '人工智能', current: 3, total: 5, percent: 60, color: '#2e7d32' },
{ name: '通信网络', current: 1, total: 10, percent: 10, color: '#f39c12' },
{ name: '量子科技', current: 0, total: 2, percent: 0, color: '#c0392b' },
{ name: '生物科技', current: 4, total: 6, percent: 66, color: '#c0392b' },
{ name: '能源', current: 8, total: 15, percent: 53, color: '#c0392b' }
],
lineData: {
xAxis: ['2022\nQ1', '2022\nQ3', '2023\nQ1', '2023\nQ3', '2024\nQ1', '2024\nQ3'],
series: {
'集成电路': [10, 20, 25, 30, 35, 32],
'量子科技': [5, 8, 12, 15, 20, 29],
'生物科技': [20, 18, 15, 17, 15, 15],
'能源': [15, 14, 18, 20, 22, 12],
'通信网络': [8, 7, 6, 5, 3, 1],
'人工智能': [12, 18, 20, 22, 15, 25]
}
}
}
}
// ==================== 2. 状态管理 ====================
const yearLeft = ref('2025')
const yearMiddle = ref('2025')
const yearRight = ref('2025')
const leftChartRef = ref(null)
const rightChartRef = ref(null)
let leftChart = null
let rightChart = null
// 计算属性:获取当前中间列表的数据
const currentPolicyList = computed(() => {
return mockDatabase[yearMiddle.value]?.policyData || []
})
// ==================== 3. 图表逻辑 ====================
// --- 左侧环形图 ---
const updateLeftChart = () => {
if (!leftChart || !leftChartRef.value) return
const data = mockDatabase[yearLeft.value]?.pieData
if (!data) return
const option = {
color: COLORS.pie,
tooltip: { trigger: 'item' },
legend: { show: false }, // 隐藏图例,直接显示Label
series: [
{
name: '建议领域',
type: 'pie',
radius: ['45%', '70%'],
center: ['50%', '55%'],
avoidLabelOverlap: true,
itemStyle: {
borderRadius: 0,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: true,
formatter: '{b}\n{c}项 {d}%',
lineHeight: 16,
color: '#606266',
fontSize: 12
},
labelLine: {
show: true,
length: 15,
length2: 10
},
data: data
}
]
}
leftChart.setOption(option)
// 确保图表正确渲染
leftChart.resize()
}
// --- 右侧折线图 ---
const updateRightChart = () => {
if (!rightChart) return
const data = mockDatabase[yearRight.value].lineData
const option = {
tooltip: { trigger: 'axis' },
legend: {
data: ['集成电路', '人工智能', '通信网络', '量子科技', '生物科技', '能源'],
top: 0,
left: 0,
icon: 'circle',
itemWidth: 8,
itemHeight: 8,
textStyle: { fontSize: 10, padding: [0, 2, 0, 0] }
},
grid: {
left: '2%',
right: '3%',
bottom: '3%',
top: '28%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false, // 折线图点在轴线上
data: data.xAxis,
axisLine: { show: false },
axisTick: { show: false },
axisLabel: { color: '#909399', fontSize: 10 }
},
yAxis: {
type: 'value',
splitLine: {
lineStyle: { type: 'dotted', color: '#ebeef5' }
},
axisLabel: { color: '#909399' }
},
series: [
{
name: '集成电路', type: 'line', smooth: false, symbol: 'circle', symbolSize: 6,
itemStyle: { color: COLORS.line.ic },
data: data.series['集成电路']
},
{
name: '量子科技', type: 'line', smooth: false, symbol: 'circle', symbolSize: 6,
itemStyle: { color: COLORS.line.quantum },
data: data.series['量子科技']
},
{
name: '生物科技', type: 'line', smooth: false, symbol: 'circle', symbolSize: 6,
itemStyle: { color: COLORS.line.bio },
data: data.series['生物科技']
},
{
name: '能源', type: 'line', smooth: false, symbol: 'circle', symbolSize: 6,
itemStyle: { color: COLORS.line.energy },
data: data.series['能源']
},
{
name: '通信网络', type: 'line', smooth: false, symbol: 'circle', symbolSize: 6,
itemStyle: { color: COLORS.line.comm },
data: data.series['通信网络']
},
{
name: '人工智能', type: 'line', smooth: false, symbol: 'circle', symbolSize: 6,
itemStyle: { color: COLORS.line.ai },
data: data.series['人工智能']
}
]
}
rightChart.setOption(option, true) // true = 不合并,完全重绘,避免旧线条残留
}
// ==================== 4. 生命周期与监听 ====================
// 监听年份变化,刷新图表
watch(yearLeft, () => updateLeftChart())
watch(yearRight, () => updateRightChart())
// 中间列表由 computed 自动处理,无需 watch
const resizeHandler = () => {
leftChart?.resize()
rightChart?.resize()
}
onMounted(() => {
nextTick(() => {
// 确保 DOM 完全渲染后再初始化
setTimeout(() => {
// 初始化实例
if (leftChartRef.value) {
leftChart = echarts.init(leftChartRef.value)
updateLeftChart()
// 确保图表正确渲染
leftChart.resize()
}
if (rightChartRef.value) {
rightChart = echarts.init(rightChartRef.value)
updateRightChart()
// 确保图表正确渲染
rightChart.resize()
}
window.addEventListener('resize', resizeHandler)
}, 100)
})
})
onUnmounted(() => {
window.removeEventListener('resize', resizeHandler)
leftChart?.dispose()
rightChart?.dispose()
})
</script>
<style lang="scss" scoped>
// 变量定义
$card-height: 360px;
$bg-color: #f5f7fa;
$text-main: #303133;
$text-sub: #909399;
$border-color: #ebeef5;
.dashboard-container {
// background-color: $bg-color;
padding: 20px;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
.dashboard-card {
height: $card-height;
display: flex;
flex-direction: column;
border: none;
border-radius: 8px;
background: #fff;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
margin-bottom: 10px; // 移动端换行间距
:deep(.el-card__header) {
padding: 15px 20px;
border-bottom: 1px solid #f0f0f0;
}
:deep(.el-card__body) {
flex: 1;
padding: 15px 20px;
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
}
}
// 头部样式
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
.title-group {
display: flex;
align-items: center;
gap: 8px;
.title {
font-weight: 700;
font-size: 16px;
color: $text-main;
}
.el-icon { font-size: 18px; }
.icon-blue { color: #409EFF; }
.icon-orange { color: #E6A23C; }
}
.link {
font-size: 12px;
color: #409EFF;
cursor: pointer;
transition: opacity 0.3s;
&:hover { opacity: 0.8; }
}
}
// 过滤器区域
.filter-row {
display: flex;
justify-content: flex-end;
margin-bottom: 10px;
z-index: 5;
.year-select {
width: 90px;
}
&.right-filter {
position: absolute;
right: 20px;
top: 15px; // 调整位置以避开图例
}
}
// ECharts 容器
.chart-container {
width: 100%;
flex: 1;
min-height: 200px; // 确保有最小高度,让图表可以渲染
height: 0; // 配合 flex: 1 使用
}
// 中间进度列表样式
.policy-list {
display: flex;
flex-direction: column;
justify-content: space-between; // 上下均匀分布
height: 100%;
padding-bottom: 5px;
.policy-item {
display: flex;
align-items: center;
font-size: 12px;
color: #606266;
.item-label {
width: 85px; // 固定宽度对齐
display: flex;
align-items: center;
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
margin-right: 8px;
flex-shrink: 0;
}
.name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
}
}
.progress-track {
flex: 1;
height: 6px;
background-color: #f2f3f5;
border-radius: 3px;
margin: 0 15px;
overflow: hidden;
.progress-bar {
height: 100%;
border-radius: 3px;
transition: width 0.5s ease; // 宽度变化动画
}
}
.item-value {
width: 110px;
display: flex;
justify-content: space-between;
color: $text-sub;
.count { font-family: Arial, sans-serif; }
.percent {
width: 35px;
text-align: right;
font-family: Arial, sans-serif;
}
}
}
}
</style>
\ No newline at end of file
<template>
<div class="report-page-container">
<!-- 顶部过滤区域 -->
<div class="top-filters">
<div class="filter-left">
<span class="filter-label" :class="{ 'active': activeTab === 'report' }" @click="activeTab = 'report'">智库报告</span>
<span class="filter-label" :class="{ 'active': activeTab === 'policy' }" @click="activeTab = 'policy'">政策建议</span>
</div>
<div class="filter-right">
<el-select v-model="selectedDateRange" placeholder="请选择" class="filter-select">
<el-option label="近一年发布" value="last_year"></el-option>
<el-option label="近三年发布" value="last_three_years"></el-option>
</el-select>
<el-select v-model="selectedSort" placeholder="请选择" class="filter-select">
<el-option label="发布时间" value="publish_time"></el-option>
<el-option label="热度" value="popularity"></el-option>
</el-select>
</div>
</div>
<el-row :gutter="24" v-if="activeTab === 'report'">
<el-col :span="5">
<div class="sidebar-filters">
<div class="filter-group">
<CardTitle title="地区筛选" style="margin-bottom: 10px"/>
<div class="checkbox-group">
<el-checkbox
v-for="region in filters.regions"
:key="region.id"
v-model="activeFilters.regions"
:label="region.id"
class="filter-checkbox"
>
{{ region.name }}
</el-checkbox>
</div>
</div>
<div class="filter-group">
<CardTitle title="智库类型" style="margin-bottom: 10px"/>
<div class="checkbox-group">
<el-checkbox
v-for="type in filters.types"
:key="type.id"
v-model="activeFilters.types"
:label="type.id"
class="filter-checkbox"
>
{{ type.name }}
</el-checkbox>
</div>
</div>
<div class="filter-group">
<CardTitle title="研究类型" style="margin-bottom: 10px"/>
<div class="checkbox-group">
<el-checkbox
v-for="research in filters.researches"
:key="research.id"
v-model="activeFilters.researches"
:label="research.id"
class="filter-checkbox"
>
{{ research.rtypeName }}
</el-checkbox>
</div>
</div>
<div class="subscription-box">
<h3>动态订阅</h3>
<p>选择您感兴趣的研究领域,获取最新报告和相关书目。</p>
<el-button type="primary" style="width: 100%;">保存订阅设置</el-button>
</div>
</div>
</el-col>
<el-col :span="19">
<div class="main-content">
<el-row :gutter="20">
<el-col :span="8" v-for="report in reportList" :key="report.id" class="card-col"
@click="handleReportClick(report)">
<el-card shadow="hover" class="report-card" :body-style="{ padding: '0px' }">
<el-image :src="$withFallbackImage(report.imageUrl, report.id) " fit="cover" class="card-image" lazy></el-image>
<div class="card-content">
<h4 class="card-title">{{ report.name }}</h4>
<div class="card-meta">
<span class="card-date">{{ report.times }}</span>
<span class="card-source">{{ report.thinkTankName }}</span>
</div>
</div>
</el-card>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
<PolicyTab v-if="activeTab === 'policy'" :showSearch="false" />
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { useRouter } from 'vue-router'
import PolicyTab from '@/components/PolicyTab.vue'
import { getOverviewReport, getThinkTankResearchType } from '@/api'
import { mockReportList } from '../mockData';
const router = useRouter()
const activeTab = ref('report')
// --- Reactive Data for Filters ---
const filters = reactive({
regions: [
{ id: 'north_america', name: '北美' },
{ id: 'europe', name: '欧洲' },
{ id: 'asia', name: '亚洲' },
{ id: 'other', name: '其他地区' },
],
types: [
{ id: 'gov', name: '政府背景' },
{ id: 'university', name: '高校附庸' },
{ id: 'independent', name: '独立智库' },
{ id: 'corporate', name: '企业视景' },
],
researches: [],
});
const activeFilters = reactive({
regions: ['north_america'],
types: ['gov'],
researches: [],
});
// --- Reactive Data for Right Content ---
const selectedDateRange = ref('last_year');
const selectedSort = ref('publish_time');
const reportList = ref([]);
const getReports = async () => {
const { data } = await getOverviewReport({
areas: activeFilters.regions,
researchTypeIds: activeFilters.researches,
})
// reportList.value = data
reportList.value = mockReportList
}
const handleReportClick = (report) => {
router.push({ name: 'ReportDetail', params: { id: report.id } })
}
const getResearchType = async () => {
const { data } = await getThinkTankResearchType()
console.log('getResearchType', data)
filters.researches = data
}
onMounted(() => {
getReports()
getResearchType()
})
</script>
<style scoped>
.report-page-container {
/* padding: 24px; */
margin-top: 20px;
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif;
}
/* --- Left Sidebar Styles --- */
.sidebar-filters {
background-color: #fff;
padding: 20px;
border-radius: 4px;
}
.filter-group {
margin-bottom: 25px;
}
.filter-title {
font-size: 16px;
font-weight: 600;
color: #303133;
margin: 0 0 15px 0;
display: flex;
align-items: center;
}
.filter-title .icon-square {
display: inline-block;
width: 4px;
height: 16px;
background-color: #409EFF;
margin-right: 8px;
border-radius: 2px;
}
/* 复选框组样式 */
.checkbox-group {
display: flex;
flex-direction: column;
gap: 4px;
}
.filter-checkbox {
margin: 0 !important;
border-radius: 4px;
transition: all 0.3s ease;
width: 100%;
display: flex;
align-items: center;
}
.filter-checkbox:hover {
background-color: #f0f2f5;
}
.subscription-box {
background-color: #f5f7fa;
border-radius: 4px;
padding: 15px;
text-align: center;
}
.subscription-box p {
font-size: 13px;
color: #909399;
line-height: 1.6;
margin: 10px 0 15px 0;
}
/* --- Right Content Styles --- */
.main-content {
/* background-color: #fff; */
/* padding: 20px; */
border-radius: 4px;
}
/* 顶部过滤区域样式 */
.top-filters {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
/* background: #fff; */
border-radius: 8px;
/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); */
margin-bottom: 10px;
}
.filter-left {
display: flex;
align-items: center;
gap: 32px;
}
.filter-label {
font-size: 16px;
color: #606266;
cursor: pointer;
position: relative;
padding: 8px 0;
transition: color 0.3s ease;
border-radius: 14px;
padding: 4px 10px;
}
.filter-label.active {
color: #fff;
background: #1459BB;
}
.filter-label:hover {
color: #409EFF;
}
.filter-right {
display: flex;
align-items: center;
gap: 12px;
}
.filter-select {
width: 140px;
}
.filter-select :deep(.el-input__wrapper) {
border-radius: 6px;
box-shadow: 0 0 0 1px #dcdfe6;
transition: box-shadow 0.3s ease;
}
.filter-select :deep(.el-input__wrapper:hover) {
box-shadow: 0 0 0 1px #409EFF;
}
.card-col {
margin-bottom: 20px;
}
.report-card {
cursor: pointer;
border-radius: 10px;
padding: 10px;
transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
}
.report-card:hover {
transform: translateY(-5px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.card-image {
width: 100%;
height: 160px;
display: block;
}
.card-content {
padding: 16px;
}
.card-title {
font-size: 15px;
font-weight: 600;
color: #303133;
margin: 0 0 10px 0;
line-height: 1.4;
/* For multi-line ellipsis */
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
.card-meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
color: #909399;
}
/* 响应式设计 */
@media (max-width: 768px) {
.top-filters {
flex-direction: column;
gap: 16px;
padding: 16px;
}
.filter-left {
width: 100%;
justify-content: center;
gap: 24px;
}
.filter-right {
width: 100%;
justify-content: center;
gap: 8px;
}
.filter-select {
width: 120px;
}
}
@media (max-width: 480px) {
.filter-left {
gap: 16px;
}
.filter-label {
font-size: 14px;
}
.filter-right {
flex-direction: column;
gap: 8px;
}
.filter-select {
width: 100%;
max-width: 200px;
}
}
</style>
\ No newline at end of file
<template>
<div class="think-tank-card" @click="handleClick">
<div class="card-header">
<div class="logo-box">
<el-image
:src="tank.logo || 'https://via.placeholder.com/60'"
:alt="tank.name"
fit="contain"
>
<template #error>
<div class="image-slot">
<el-icon><Picture /></el-icon>
</div>
</template>
</el-image>
</div>
<div class="rank-badge" v-if="index !== undefined">
<span class="rank-text">No.{{ index + 1 }}</span>
</div>
</div>
<div class="title-row">
<div class="tank-name" :title="tank.name">{{ tank.name }}</div>
<div class="tank-country">{{ tank.country }}</div>
</div>
<div class="tank-description" :title="tank.describe">
{{ tank.describe }}
</div>
<div class="tank-tags">
<span
v-for="(tag, idx) in tank.tags"
:key="tag"
class="custom-tag"
:class="idx % 2 === 0 ? 'tag-blue' : 'tag-red'"
>
{{ tag }}
</span>
</div>
</div>
</template>
<script setup>
import { Picture } from '@element-plus/icons-vue' // 引入图标用于图片加载失败占位
const props = defineProps({
tank: {
type: Object,
required: true
},
// 新增 index用于显示 No.1, No.2 等排名
index: {
type: Number,
default: 0
}
})
const emit = defineEmits(['click'])
const handleClick = () => {
emit('click', props.tank)
}
</script>
<style scoped lang="scss">
.think-tank-card {
background: #ffffff;
border-radius: 12px; // 更圆润的角
padding: 16px;
width: 280px; // 稍微加宽以匹配设计图比例,可根据父容器自适应
// border: 1px solid #e4e7ed; // 设计图看起来边框很淡,或者主要是阴影
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
display: flex;
flex-direction: column;
cursor: pointer;
position: relative;
transition: all 0.3s ease;
overflow: hidden; // 确保排名背景不溢出
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.1);
}
}
/* --- 顶部区域 --- */
.card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 12px;
position: relative;
}
.logo-box {
width: 48px;
height: 48px;
// 设计图中Logo是自适应显示的,取消了灰底
display: flex;
align-items: center;
justify-content: center;
.el-image {
width: 100%;
height: 100%;
border-radius: 4px;
display: block; // 消除图片底部间隙
}
.image-slot {
width: 100%;
height: 100%;
background: #f5f7fa;
display: flex;
justify-content: center;
align-items: center;
color: #909399;
}
}
/* 排名条样式 */
.rank-badge {
/* 绝对定位到右上角,或者利用Flex布局 */
position: absolute;
right: -16px; /* 抵消父级padding */
top: -6px; /* 微调垂直位置 */
height: 32px;
padding-left: 30px; /* 渐变过度区 */
padding-right: 16px;
display: flex;
align-items: center;
justify-content: flex-end;
/* 核心:背景渐变从透明到淡红色 */
background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(206, 126, 126, 0.15) 40%, rgba(199, 58, 58, 0.15) 100%);
.rank-text {
font-family: 'Impact', sans-serif, 'Arial Black'; /* 选用粗体字体 */
font-size: 20px;
font-style: italic;
color: #b54646; /* 暗红色字体 */
letter-spacing: 1px;
}
}
/* --- 标题行 --- */
.title-row {
display: flex;
justify-content: space-between;
align-items: baseline; /* 文字基线对齐 */
margin-bottom: 12px;
}
.tank-name {
font-size: 16px;
font-weight: 700;
color: #303133;
line-height: 1.4;
margin-right: 8px;
/* 防止名字太长换行导致布局崩坏,可按需开启截断 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tank-country {
font-size: 13px;
color: #909399;
flex-shrink: 0;
}
/* --- 描述文本 --- */
.tank-description {
font-size: 13px;
color: #606266;
line-height: 1.6;
margin-bottom: 16px;
min-height: 63px; /* 预留3行高度,保证卡片高度一致 */
/* 3行省略号 */
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
text-overflow: ellipsis;
}
/* --- 底部标签 --- */
.tank-tags {
display: flex;
gap: 8px;
margin-top: auto; /* 推到底部 */
}
/* 自定义标签样式,模拟设计图 */
.custom-tag {
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
border: 1px solid transparent; // 预留边框位置
&.tag-blue {
background-color: #e6f1fc; /* 淡蓝背景 */
color: #409eff; /* 蓝色文字 */
border-color: #d9ecff;
}
&.tag-red {
background-color: #fef0f0; /* 淡红背景 */
color: #f56c6c; /* 红色文字 */
border-color: #fde2e2;
}
}
</style>
\ No newline at end of file
...@@ -112,7 +112,27 @@ ...@@ -112,7 +112,27 @@
<div class="title">{{ "智库发布" }}</div> <div class="title">{{ "智库发布" }}</div>
</div> </div>
</div> </div>
<div class="box1-main"></div> <div class="box1-main">
<div class="box1-main-left">
<img :src="box1Data.img" alt="" />
</div>
<div class="box1-main-right">
<div class="title">{{ box1Data.title }}</div>
<div class="tag-box">
<div class="tag" v-for="(item, index) in box1Data.tagList" :key="index">{{ item }}</div>
</div>
<div class="content">{{ box1Data.content }}</div>
<div class="box1-right-footer">
<div class="time">{{ box1Data.time }}</div>
<div class="name">
<div class="logo">
<img :src="box1Data.logo" alt="" />
</div>
<div class="text">{{ box1Data.from }}</div>
</div>
</div>
</div>
</div>
</div> </div>
<div class="box2"> <div class="box2">
<div class="box2-header"> <div class="box2-header">
...@@ -186,6 +206,24 @@ ...@@ -186,6 +206,24 @@
</div> </div>
<div class="header-title">{{ "智库人物动态" }}</div> <div class="header-title">{{ "智库人物动态" }}</div>
</div> </div>
<div class="box4-tag-box">
<div
class="tag"
:class="{
tagActive: box4ActiveTag === tag.name,
tag1: tag.status === 1,
tag2: tag.status === 2,
tag3: tag.status === 3,
tag4: tag.status === 4,
tag5: tag.status === 5
}"
v-for="(tag, index) in box4TagList"
:key="index"
@click="handleClickBox4Tag(tag.name)"
>
{{ tag.name }}
</div>
</div>
<div class="box4-main"> <div class="box4-main">
<div class="box4-main-item" v-for="(item, index) in messageList" :key="index"> <div class="box4-main-item" v-for="(item, index) in messageList" :key="index">
<div class="left"> <div class="left">
...@@ -317,66 +355,42 @@ ...@@ -317,66 +355,42 @@
<div class="select-box"> <div class="select-box">
<div class="header"> <div class="header">
<div class="icon"></div> <div class="icon"></div>
<div class="title">{{ "地区筛选" }}</div> <div class="title">{{ "科技领域" }}</div>
</div> </div>
<div class="select-main"> <div class="select-main">
<div class="checkbox-group"> <div class="checkbox-group">
<el-checkbox <el-checkbox
v-for="region in filters.regions" v-for="research in areaList"
:key="region.id" :key="research.id"
v-model="activeFilters.regions" v-model="selectedAreaList"
:label="region.id" :label="research.id"
class="filter-checkbox"
>
{{ region.name }}
</el-checkbox>
</div>
</div>
</div>
<div class="select-box">
<div class="header">
<div class="icon"></div>
<div class="title">{{ "智库类型" }}</div>
</div>
<div class="select-main select-main1">
<div class="checkbox-group">
<el-checkbox
v-for="type in filters.types"
:key="type.id"
v-model="activeFilters.types"
:label="type.id"
class="filter-checkbox" class="filter-checkbox"
> >
{{ type.name }} {{ research.name }}
</el-checkbox> </el-checkbox>
</div> </div>
</div> </div>
</div> </div>
<div class="select-box"> <div class="select-box">
<div class="header"> <div class="header">
<div class="icon"></div> <div class="icon"></div>
<div class="title">{{ "研究领域" }}</div> <div class="title">{{ "发布时间" }}</div>
</div> </div>
<div class="select-main"> <div class="select-main">
<div class="checkbox-group"> <div class="checkbox-group">
<el-checkbox <el-checkbox
v-for="research in filters.researches" v-for="time in pubTimeList"
:key="research.id" :key="time.id"
v-model="activeFilters.researches" v-model="selectedPubTimeList"
:label="research.id" :label="time.id"
class="filter-checkbox" class="filter-checkbox"
> >
{{ research.name }} {{ time.name }}
</el-checkbox> </el-checkbox>
</div> </div>
</div> </div>
</div> </div>
<div class="left-footer-box">
<div class="header">{{ "动态订阅" }}</div>
<div class="content">{{ "选择您感兴趣的研究领域,获取最新报告通知" }}</div>
<div class="btn">{{ "保存订阅设置" }}</div>
</div>
</div> </div>
<div class="right"> <div class="right">
<div class="card-box"> <div class="card-box">
...@@ -409,7 +423,7 @@ ...@@ -409,7 +423,7 @@
</template> </template>
<script setup> <script setup>
import { onMounted, ref, reactive } from "vue"; import { onMounted, ref, computed, reactive } from "vue";
import scrollToTop from "@/utils/scrollToTop"; import scrollToTop from "@/utils/scrollToTop";
import router from "@/router"; import router from "@/router";
import DivideHeader from "@/components/DivideHeader.vue"; import DivideHeader from "@/components/DivideHeader.vue";
...@@ -425,9 +439,6 @@ import { ...@@ -425,9 +439,6 @@ import {
import getMultiLineChart from "./utils/multiLineChart"; import getMultiLineChart from "./utils/multiLineChart";
import getPieChart from "./utils/piechart"; import getPieChart from "./utils/piechart";
import getRadarChart from "./utils/radarChart";
import getMapChart from "./utils/mapChart";
import getBarChart from "./utils/barChart";
import getSankeyChart from "./utils/sankey"; import getSankeyChart from "./utils/sankey";
import News1 from "./assets/images/news1.png"; import News1 from "./assets/images/news1.png";
...@@ -459,68 +470,10 @@ import Img10 from "./assets/images/img10.png"; ...@@ -459,68 +470,10 @@ import Img10 from "./assets/images/img10.png";
import Img11 from "./assets/images/img11.png"; import Img11 from "./assets/images/img11.png";
import Img12 from "./assets/images/img12.png"; import Img12 from "./assets/images/img12.png";
const handleClick = tank => { import Box1Img from "./assets/images/box1-img.png";
// router.push({ name: "ThinkTankDetail", params: { id: tank.id } }); import Box1Logo from "./assets/images/box1-logo.png";
const curRoute = router.resolve({ name: "ThinkTankDetail", params: { id: tank.id } });
window.open(curRoute.href, "_blank");
};
const activeFilters = reactive({
regions: ["north_america"],
types: ["gov"],
researches: ["全部领域"]
});
const filters = reactive({
regions: [
{ id: "north_america", name: "北美" },
{ id: "europe", name: "欧洲" },
{ id: "asia", name: "亚洲" },
{ id: "other", name: "其他地区" }
],
types: [
{ id: "gov", name: "政府背景" },
{ id: "university", name: "高校附属" },
{ id: "independent", name: "独立智库" },
{ id: "corporate", name: "企业视景" }
],
researches: [
{
id: "全部领域",
name: "全部领域"
},
{
id: "人工智能",
name: "人工智能"
},
{
id: "通信网络",
name: "通信网络"
},
{
id: "量子科技",
name: "量子科技"
},
{
id: "能源",
name: "能源"
},
{
id: "生物技术",
name: "生物技术"
},
{
id: "新材料",
name: "新材料"
},
{
id: "海洋",
name: "海洋"
}
]
});
// 智库列表
const cardList = ref([ const cardList = ref([
// { // {
// id: 1, // id: 1,
...@@ -557,78 +510,78 @@ const cardList = ref([ ...@@ -557,78 +510,78 @@ const cardList = ref([
// status: 1 // status: 1
// } // }
// ] // ]
// },
// {
// id: 3,
// logo: Logo3,
// rank: 3,
// name: "麦肯锡全球研究院",
// country: "美国",
// desc: "专注于国际安全、国防、区域研究、能源与气候变化等领域,以其强硬的安全政策立场著称。 ",
// tagList: [
// {
// name: "国际安全",
// status: 2
// },
// {
// name: "国防政策",
// status: 4
// }
// ]
// },
// {
// id: 4,
// logo: Logo4,
// rank: 4,
// name: "麻省理工学院科技评论",
// country: "美国",
// desc: "全球顶尖政策研究机构,专注于国家安全、科技政策、医疗卫生、能源政策、公共安全等领域的研究。 ",
// tagList: [
// {
// name: "公共政策",
// status: 2
// },
// {
// name: "国际关系",
// status: 4
// }
// ]
// },
// {
// id: 5,
// logo: Logo5,
// rank: 5,
// name: "信息技术与创新基金会",
// country: "美国",
// desc: "专注于国内外公共政策、国际关系等领域,是美国最具影响力的官方智库之一。 ",
// tagList: [
// {
// name: "公共政策",
// status: 2
// },
// {
// name: "国家安全",
// status: 4
// }
// ]
// } // }
]); ]);
// 获取智库列表
// 返回首页 const handleGetThinkTankList = async () => {
const handleBackHome = () => { try {
router.push({ const res = await getThinkTankList();
path: "/overview" console.log("智库列表", res);
}); if (res.code === 200 && res.data) {
cardList.value = res.data.map(item => {
return {
id: item.id,
logo: item.imageUrl,
name: item.name,
tagList: item.tags,
country: item.country,
desc: item.describe,
rank: item.id
};
});
}
} catch (error) {
console.error("获取智库列表error", error);
}
}; };
const handleClickToDetail = id => { // 智库发布
const route = router.resolve({ const box1Data = ref({
path: "/marketAccessLayout", img: Box1Img,
query: { title: "中美经济竞争:复杂经济和地缘政治关系中的收益和风险",
id: id tagList: ["外交", "军事", "经济"],
content: `自2017年以来,美中竞争,包括经济竞争,已成为美国外交政策的定义。这两个经济体是世界上第一和第二大国家经济体,彼此紧密交织。无论多么必要的关系变化,都可能付出高昂代价。因此,美国面临着在双重战略竞争条件下确保其经济满足国家需求的挑战。为应对这一挑战,兰德研究人员对美中竞争进行了经济和制度分析,开展了参与式前瞻性研究,以理解确保美国经济健全发展`,
time: "2025年9月16日",
from: "兰德科技智库",
logo: Box1Logo
});
// 风险信号
const warningList = ref([
{
title: "关于对中华人民共和国合成阿片类药物供应链...",
time: "一天前",
status: "特别重大"
},
{
title: "关于调整钢铁进口的公告",
time: "一天前",
status: "重大风险"
},
{
title: "关于修订对中华人民共和国低价值进口商品适...",
time: "一天前",
status: "一般风险"
}
]);
// 获取智库风险信号
const handleGetThinkTankRiskSignal = async () => {
try {
const res = await getThinkTankRiskSignal();
console.log("智库风险信号", res);
if (res.code === 200) {
warningList.value = res.data.map(item => {
return {
title: item.name,
time: item.times,
id: item.reportId,
status: item.riskLevel || "暂无数值"
};
});
} }
}); } catch (error) {
window.open(route.href, "_blank"); console.error("获取智库风险信号error", error);
}
}; };
// 新闻资讯 // 新闻资讯
...@@ -665,7 +618,38 @@ const newsList = ref([ ...@@ -665,7 +618,38 @@ const newsList = ref([
} }
]); ]);
// 社交媒体 // 智库人物动态
const box4TagList = ref([
{
name: "新能源",
status: 3
},
{
name: "人工智能",
status: 2
},
{
name: "通信网络",
status: 2
},
{
name: "量子科技",
status: 5
},
{
name: "生物科技",
status: 1
},
{
name: "集成电路",
status: 4
}
]);
const box4ActiveTag = ref("通信网络");
const handleClickBox4Tag = (tag) => {
box4ActiveTag.value = tag
}
const messageList = ref([ const messageList = ref([
{ {
img: Message1, img: Message1,
...@@ -687,165 +671,64 @@ const messageList = ref([ ...@@ -687,165 +671,64 @@ const messageList = ref([
} }
]); ]);
// 风险信号 // 政策建议趋势分布
const warningList = ref([ const box5Data = ref({
{ title: ["2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
title: "关于对中华人民共和国合成阿片类药物供应链...", data: [
time: "一天前", {
status: "特别重大" name: "人工智能",
}, value: [73, 32, 42, 48, 38, 49, 63, 75, 70, 86, 95, 87]
{ },
title: "关于调整汽车及汽车零部件进口的公告", {
time: "一天前", name: "集成电路",
status: "特别重大" value: [8, 3, 2, 8, 9, 10, 12, 18, 16, 18, 20, 22]
}, },
{
name: "量子科技",
value: [1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 2, 3]
}
]
});
const box5selectetedYear = ref("近十年");
const box5YearList = ref([
{ {
title: "关于调整钢铁进口的公告", label: "近十年",
time: "一天前", value: "近十年"
status: "重大风险"
}, },
{ {
title: "关于使用互惠关税规范进口以纠正导致大规模...", label: "近五年",
time: "一天前", value: "近五年"
status: "重大风险"
}, },
{ {
title: "关于修订对中华人民共和国低价值进口商品适...", label: "近三年",
time: "一天前", value: "近三年"
status: "一般风险"
} }
]); ]);
// 政策建议趋势分布
const categoryList = ref(["智库报告", "政策建议"]); const handleGetThinkTankPolicyIndustryChange = async () => {
try {
const activeCate = ref("智库报告"); const res = await getThinkTankPolicyIndustryChange();
const activeHylyId = ref(""); console.log("政策建议趋势分布", res);
if (res.code === 200 && res.data) {
const handleClickCate = cate => { } else {
console.log(cate); box5Data.value = [];
}
activeCate.value = cate; } catch (error) {
activeHylyId.value = cate; console.error("获取政策建议趋势分布error", error);
handleGetBillsByType(); }
};
const handleBox5 = async () => {
await handleGetThinkTankPolicyIndustryChange();
let box5Chart = getMultiLineChart(
box5Data.value.title,
box5Data.value.data[0].value,
box5Data.value.data[1].value,
box5Data.value.data[2].value
);
setChart(box5Chart, "box5Chart");
}; };
// 政策建议领域分布
// 查看更多风险信号
const handleToMoreRiskSignal = () => {
const route = router.resolve("/riskSignal");
window.open(route.href, "_blank");
};
const curFooterList = ref([
{
title: "中国对AI的转型产业政策",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img1
},
{
title: "中美对抗、竞争和合作跨越人工智能通用领域...",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img2
},
{
title: "中国、智慧城市和中东:地区和美国的选择",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img3
},
{
title: "中国对AI的转型产业政策",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img4
},
{
title: "中美经济竞争:复杂经济和地缘政治关系中的...",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img5
},
{
title: "中国、智慧城市和中东:留给地区和美国的选择",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img6
},
{
title: "中国对AI的转型产业政策",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img7
},
{
title: "中美对抗、竞争和合作跨越人工智能通用领域...",
time: "2025年6月26日",
from: "",
img: Img8
},
{
title: "中国、智慧城市和中东:地区和美国的选择",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img9
},
{
title: "中国对AI的转型产业政策",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img10
},
{
title: "中美对抗、竞争和合作跨越人工智能通用领域...",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img11
},
{
title: "中国、智慧城市和中东:地区和美国的选择",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img12
}
]);
const box5Data = ref({
title: ["2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025"],
data: [
{
name: "人工智能",
value: [73, 32, 42, 48, 38, 49, 63, 75, 70, 86, 95, 87]
},
{
name: "集成电路",
value: [8, 3, 2, 8, 9, 10, 12, 18, 16, 18, 20, 22]
},
{
name: "量子科技",
value: [1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 2, 3]
}
]
});
const box5selectetedYear = ref("近十年");
const box5YearList = ref([
{
label: "近十年",
value: "近十年"
},
{
label: "近五年",
value: "近五年"
},
{
label: "近三年",
value: "近三年"
}
]);
const box6Data = ref([ const box6Data = ref([
{ {
name: "半导体", name: "半导体",
...@@ -883,7 +766,6 @@ const box6Data = ref([ ...@@ -883,7 +766,6 @@ const box6Data = ref([
color: "#D6E4FF" color: "#D6E4FF"
} }
]); ]);
const box6selectetedYear = ref("2025"); const box6selectetedYear = ref("2025");
const box6YearList = ref([ const box6YearList = ref([
{ {
...@@ -903,6 +785,29 @@ const box6YearList = ref([ ...@@ -903,6 +785,29 @@ const box6YearList = ref([
value: "2022" value: "2022"
} }
]); ]);
// 政策建议领域分布
const handleGetThinkTankPolicyIndustry = async () => {
const params = {
apply: 1,
yaer: box6selectetedYear.value
};
try {
const res = await getThinkTankPolicyIndustry(params);
console.log("政策建议领域分布", res);
if (res.code === 200 && res.data) {
} else {
box6Data.value = [];
}
} catch (error) {
console.error("获取政策建议领域分布error", error);
}
};
const handleBox6 = async () => {
await handleGetThinkTankPolicyIndustry();
const box6Chart = getPieChart(box6Data.value);
setChart(box6Chart, "box6Chart");
};
// 智库资金流向 // 智库资金流向
const box7Data = ref({ const box7Data = ref({
...@@ -942,6 +847,88 @@ const box7Data = ref({ ...@@ -942,6 +847,88 @@ const box7Data = ref({
{ source: "美国国务院", target: "兰德公司", value: 15 } { source: "美国国务院", target: "兰德公司", value: 15 }
] ]
}); });
function transformThinkTankData(data) {
const nodes = [];
const links = [];
const nodeSet = new Set(); // 用于去重
// 遍历每个智库
data.forEach(thinkTank => {
const thinkTankName = thinkTank.thinkTankName;
// 添加智库节点
if (!nodeSet.has(thinkTankName)) {
nodes.push({ name: thinkTankName });
nodeSet.add(thinkTankName);
}
// 遍历每个资金来源
thinkTank.thinkTankDonationSourceVOList.forEach(source => {
const { amount, institution, secondInstitution } = source;
// 处理机构节点
if (institution && !nodeSet.has(institution)) {
nodes.push({ name: institution });
nodeSet.add(institution);
}
// 处理二级机构节点
if (secondInstitution && !nodeSet.has(secondInstitution)) {
nodes.push({ name: secondInstitution });
nodeSet.add(secondInstitution);
}
// 构建链接
if (institution && secondInstitution) {
// 情况1: institution → secondInstitution → thinkTankName
links.push({
source: institution,
target: secondInstitution,
value: amount
});
links.push({
source: secondInstitution,
target: thinkTankName,
value: amount
});
} else if (institution && !secondInstitution) {
// 情况2: institution → thinkTankName
links.push({
source: institution,
target: thinkTankName,
value: amount
});
} else if (!institution && !secondInstitution) {
// 情况3: 只有智库节点
links.push({
source: thinkTankName,
value: amount
});
}
});
});
return { nodes, links };
}
// 智库资金流向
const handleGetThinkTankDonation = async () => {
try {
const res = await getThinkTankDonation();
console.log("智库资金流向", res);
if (res.code === 200 && res.data) {
box7Data.value = transformThinkTankData(res.data);
}
} catch (error) {
console.error("获取智库资金流向error", error);
}
};
const handleBox7 = async () => {
await handleGetThinkTankDonation();
const box7Chart = getSankeyChart(box7Data.value.nodes, box7Data.value.links);
setChart(box7Chart, "box7Chart");
};
// 智库研究热点 // 智库研究热点
const box8Data = ref([ const box8Data = ref([
...@@ -1003,190 +990,182 @@ const box8YearList = ref([ ...@@ -1003,190 +990,182 @@ const box8YearList = ref([
} }
]); ]);
// 获取智库列表 // 资源库
const handleGetThinkTankList = async () => { const categoryList = ref(["智库报告", "政策建议"]);
try { const activeCate = ref("智库报告");
const res = await getThinkTankList(); const handleClickCate = cate => {
console.log("智库列表", res); activeCate.value = cate;
if (res.code === 200 && res.data) {
cardList.value = res.data.map(item => {
return {
id: item.id,
logo: item.imageUrl,
name: item.name,
tagList: item.tags,
country: item.country,
desc: item.describe,
rank: item.id
};
});
}
} catch (error) {
console.error("获取智库列表error", error);
}
};
// 获取智库风险信号
const handleGetThinkTankRiskSignal = async () => {
try {
const res = await getThinkTankRiskSignal();
console.log("智库风险信号", res);
if (res.code === 200) {
warningList.value = res.data.map(item => {
return {
title: item.name,
time: item.times,
id: item.reportId,
status: item.riskLevel || "暂无数值"
};
});
}
} catch (error) {
console.error("获取智库风险信号error", error);
}
}; };
// 政策建议趋势分布 const areaList = ref([
const handleGetThinkTankPolicyIndustryChange = async () => { {
try { id: "全部领域",
const res = await getThinkTankPolicyIndustryChange(); name: "全部领域"
console.log("政策建议趋势分布", res); },
if(res.code === 200 && res.data) { {
id: "人工智能",
name: "人工智能"
},
{
id: "通信网络",
name: "通信网络"
},
{
id: "量子科技",
name: "量子科技"
},
{
id: "能源",
name: "能源"
},
{
id: "生物技术",
name: "生物技术"
},
} else { {
box5Data.value = [] id: "新材料",
} name: "新材料"
} catch (error) { },
console.error("获取政策建议趋势分布error", error); {
id: "海洋",
name: "海洋"
} }
}; ]);
const selectedAreaList = ref(["全部领域"]);
const handleBox5 = async() => { const pubTimeList = ref([
await handleGetThinkTankPolicyIndustryChange() {
let box5Chart = getMultiLineChart( id: "全部时间",
box5Data.value.title, name: "全部时间"
box5Data.value.data[0].value, },
box5Data.value.data[1].value, {
box5Data.value.data[2].value id: "2025年",
); name: "2025年"
setChart(box5Chart, "box5Chart"); },
} {
id: "2024年",
name: "2024年"
},
{
id: "2023年",
name: "2023年"
},
{
id: "2022年",
name: "2022年"
},
{
id: "2021年",
name: "2021年"
},
{
id: "更早时间",
name: "更早时间"
}
]);
const selectedPubTimeList = ref(["全部时间"]);
// 政策建议趋势分布 const curFooterList = ref([
const handleGetThinkTankPolicyIndustry = async () => { {
const params = { title: "中国对AI的转型产业政策",
apply: 1, time: "2025年6月26日",
yaer: box6selectetedYear.value from: "兰德科技智库",
img: Img1
},
{
title: "中美对抗、竞争和合作跨越人工智能通用领域...",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img2
},
{
title: "中国、智慧城市和中东:地区和美国的选择",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img3
},
{
title: "中国对AI的转型产业政策",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img4
},
{
title: "中美经济竞争:复杂经济和地缘政治关系中的...",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img5
},
{
title: "中国、智慧城市和中东:留给地区和美国的选择",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img6
},
{
title: "中国对AI的转型产业政策",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img7
},
{
title: "中美对抗、竞争和合作跨越人工智能通用领域...",
time: "2025年6月26日",
from: "",
img: Img8
},
{
title: "中国、智慧城市和中东:地区和美国的选择",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img9
},
{
title: "中国对AI的转型产业政策",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img10
},
{
title: "中美对抗、竞争和合作跨越人工智能通用领域...",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img11
},
{
title: "中国、智慧城市和中东:地区和美国的选择",
time: "2025年6月26日",
from: "兰德科技智库",
img: Img12
} }
try { ]);
const res = await getThinkTankPolicyIndustry(params);
console.log("政策建议领域分布", res);
if(res.code === 200 && res.data) {
} else { const handleClick = tank => {
box6Data.value = [] // router.push({ name: "ThinkTankDetail", params: { id: tank.id } });
} const curRoute = router.resolve({ name: "ThinkTankDetail", params: { id: tank.id } });
} catch (error) { window.open(curRoute.href, "_blank");
console.error("获取政策建议领域分布error", error);
}
}; };
const handleBox6 = async() => { // 返回首页
await handleGetThinkTankPolicyIndustry() const handleBackHome = () => {
const box6Chart = getPieChart(box6Data.value); router.push({
setChart(box6Chart, "box6Chart"); path: "/overview"
}
function transformThinkTankData(data) {
const nodes = [];
const links = [];
const nodeSet = new Set(); // 用于去重
// 遍历每个智库
data.forEach(thinkTank => {
const thinkTankName = thinkTank.thinkTankName;
// 添加智库节点
if (!nodeSet.has(thinkTankName)) {
nodes.push({ name: thinkTankName });
nodeSet.add(thinkTankName);
}
// 遍历每个资金来源
thinkTank.thinkTankDonationSourceVOList.forEach(source => {
const { amount, institution, secondInstitution } = source;
// 处理机构节点
if (institution && !nodeSet.has(institution)) {
nodes.push({ name: institution });
nodeSet.add(institution);
}
// 处理二级机构节点
if (secondInstitution && !nodeSet.has(secondInstitution)) {
nodes.push({ name: secondInstitution });
nodeSet.add(secondInstitution);
}
// 构建链接
if (institution && secondInstitution) {
// 情况1: institution → secondInstitution → thinkTankName
links.push({
source: institution,
target: secondInstitution,
value: amount
});
links.push({
source: secondInstitution,
target: thinkTankName,
value: amount
});
} else if (institution && !secondInstitution) {
// 情况2: institution → thinkTankName
links.push({
source: institution,
target: thinkTankName,
value: amount
});
} else if (!institution && !secondInstitution) {
// 情况3: 只有智库节点
links.push({
source: thinkTankName,
value: amount
});
}
});
}); });
return { nodes, links };
}
// 智库资金流向
const handleGetThinkTankDonation = async () => {
try {
const res = await getThinkTankDonation();
console.log("智库资金流向", res);
if (res.code === 200 && res.data) {
box7Data.value = transformThinkTankData(res.data);
}
} catch (error) {
console.error("获取智库资金流向error", error);
}
}; };
const handleBox7 = async () => {
await handleGetThinkTankDonation(); // 查看更多风险信号
const box7Chart = getSankeyChart(box7Data.value.nodes, box7Data.value.links); const handleToMoreRiskSignal = () => {
setChart(box7Chart, "box7Chart"); const route = router.resolve("/riskSignal");
window.open(route.href, "_blank");
}; };
onMounted(async () => { onMounted(async () => {
handleGetThinkTankList(); handleGetThinkTankList();
handleGetThinkTankRiskSignal(); handleGetThinkTankRiskSignal();
handleBox5() handleBox5();
handleBox6() handleBox6();
handleBox7(); handleBox7();
}); });
</script> </script>
...@@ -1583,10 +1562,113 @@ onMounted(async () => { ...@@ -1583,10 +1562,113 @@ onMounted(async () => {
} }
} }
.box1-main { .box1-main {
width: 1064px; margin: 24px auto;
height: 354px; width: 948px;
margin-top: 22px; height: 353px;
margin-left: 31px; display: flex;
gap: 28px;
.box1-main-left {
width: 458px;
height: 353px;
border-radius: 4px;
img {
width: 100%;
height: 100%;
}
}
.box1-main-right {
width: 462px;
.title {
width: 462px;
max-height: 52px;
overflow: hidden;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px;
text-align: left;
}
.tag-box {
width: 462px;
height: 26px;
overflow: hidden;
margin-top: 16px;
display: flex;
gap: 8px;
.tag {
height: 26px;
padding: 0 8px;
box-sizing: border-box;
border: 1px solid rgba(231, 243, 255, 1);
border-radius: 4px;
background: rgba(246, 250, 255, 1);
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
}
.content {
margin-top: 17px;
width: 462px;
height: 183px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
display: -webkit-box;
-webkit-line-clamp: 6; /* 限制行数为5 */
-webkit-box-orient: vertical;
overflow: hidden;
}
.box1-right-footer {
margin-top: 31px;
display: flex;
justify-content: space-between;
.time {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
.name {
display: flex;
justify-content: flex-end;
gap: 6px;
.logo {
margin-top: 5px;
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: right;
}
}
}
}
} }
} }
.box2 { .box2 {
...@@ -1922,15 +2004,70 @@ onMounted(async () => { ...@@ -1922,15 +2004,70 @@ onMounted(async () => {
cursor: pointer; cursor: pointer;
} }
} }
.box4-tag-box {
height: 60px;
display: flex;
padding: 0 10px;
align-items: center;
gap: 8px;
.tag {
height: 28px;
line-height: 28px;
padding: 0 4px;
box-sizing: border-box;
border-radius: 4px;
cursor: pointer;
}
.tagActive {
height: 36px;
line-height: 36px;
box-sizing: border-box;
border: 1px solid rgba(114, 46, 209, 1) !important;
border-radius: 4px;
background: rgba(114, 46, 209, 1) !important;
color: rgba(249, 240, 255, 1) !important;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 36px;
letter-spacing: 1px;
}
.tag1 {
border: 1px solid rgba(135, 232, 222, 1);
background: rgba(230, 255, 251, 1);
color: rgba(19, 168, 168, 1);
}
.tag2 {
border: 1px solid rgba(145, 202, 255, 1);
background: rgba(230, 244, 255, 1);
color: rgba(22, 119, 255, 1);
}
.tag3 {
border: 1px solid rgba(255, 213, 145, 1);
background: rgba(255, 247, 230, 1);
color: rgba(250, 140, 22, 1);
}
.tag4 {
border: 1px solid rgba(255, 187, 150, 1);
background: rgba(255, 242, 232, 1);
color: rgba(250, 84, 28, 1);
}
.tag5 {
border: 1px solid rgba(255, 163, 158, 1);
background: rgba(255, 241, 240, 1);
color: rgba(206, 79, 81, 1);
}
}
.box4-main { .box4-main {
height: 402px; height: 342px;
overflow-y: auto; overflow-y: auto;
box-sizing: border-box; box-sizing: border-box;
padding-top: 8px; padding: 8px 0;
.box4-main-item { .box4-main-item {
margin-top: 16px; margin-top: 16px;
display: flex; display: flex;
margin-left: 21px; margin-left: 21px;
.left { .left {
margin-top: 5px; margin-top: 5px;
width: 36px; width: 36px;
...@@ -1947,6 +2084,7 @@ onMounted(async () => { ...@@ -1947,6 +2084,7 @@ onMounted(async () => {
border: 1px solid rgba(231, 243, 255, 1); border: 1px solid rgba(231, 243, 255, 1);
background: rgba(246, 250, 255, 1); background: rgba(246, 250, 255, 1);
padding: 10px 15px; padding: 10px 15px;
border-radius: 4px;
.right-top { .right-top {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -2329,7 +2467,7 @@ onMounted(async () => { ...@@ -2329,7 +2467,7 @@ onMounted(async () => {
gap: 16px; gap: 16px;
.left { .left {
width: 300px; width: 300px;
height: 806px; height: 600px;
box-sizing: border-box; box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1); border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px; border-radius: 10px;
...@@ -2492,6 +2630,9 @@ onMounted(async () => { ...@@ -2492,6 +2630,9 @@ onMounted(async () => {
margin-top: 52px; margin-top: 52px;
margin-bottom: 36px; margin-bottom: 36px;
} }
.filter-checkbox {
width: 105px;
}
:deep(.el-input__wrapper) { :deep(.el-input__wrapper) {
box-shadow: none; box-shadow: none;
border-radius: 10px; border-radius: 10px;
......
import { reverse } from "d3";
import * as echarts from "echarts";
const getBarChart = (originalData) => {
// 按 value 从大到小排序
const sortedData = [...originalData].sort((a, b) => b.value - a.value);
const option = {
tooltip: {},
grid: {
top: '3%',
right: '3%',
bottom: '1%',
left: '1%',
containLabel: true
},
xAxis: {
type: 'value',
splitLine: {
show: false
},
show: false
},
yAxis: {
type: 'category',
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLine: {
show: false
},
axisLabel: {
show: true,
formatter: function (value, index) {
// index 是从 0 开始的
const rank = index + 1;
// 基础版本
// return `${rank}. ${value}`;
// 带样式的版本
return `{rank|${rank}} {name|${value}}`;
},
// 启用富文本
rich: {
rank: {
color: 'rgba(5, 95, 194, 1)', // 序号颜色
fontFamily: 'Microsoft YaHei',
fontSize: 12, // 字体大小
width: 24,
height: 24,
align: 'center',
verticalAlign: 'middle',
backgroundColor: 'rgba(231, 243, 255, 1)',
borderRadius: 12,
padding: [0, 0]
},
name: {
color: '#333', // 名称颜色
fontSize: 12
}
}
},
data: sortedData.map(item => item.name),
inverse: true, // Y轴反向,使第一个在顶部
},
series: [{
type: 'bar',
data: sortedData.map(item => item.value),
label: {
show: true,
position: [300, 0],
formatter: function (params) {
return params.value + ' 次'
}
},
barWidth: 8,
itemStyle: {
color: function (params) {
if (params.dataIndex === 0) {
return new echarts.graphic.LinearGradient(0, 0, 1, 0,
[{
offset: 0,
color: 'rgba(206, 79, 81, 0)'
},
{
offset: 1,
color: 'rgba(206, 79, 81, 1)'
}
]);
} else if (params.dataIndex < 3) {
return new echarts.graphic.LinearGradient(0, 0, 1, 0,
[{
offset: 0,
color: 'rgba(255, 172, 77, 0)'
},
{
offset: 1,
color: 'rgba(255, 172, 77, 1)'
}
]);
} else {
return new echarts.graphic.LinearGradient(0, 0, 1, 0,
[{
offset: 0,
color: 'rgba(5, 95, 194, 0)'
},
{
offset: 1,
color: 'rgba(5, 95, 194, 1)'
}
]);
}
},
barBorderRadius: 4,
}
}]
}
return option
}
export default getBarChart
\ No newline at end of file
import * as echarts from 'echarts'
import chinaJson from '@/assets/json/China.json'
const getMapChart = (mapData) => {
echarts.registerMap('china', chinaJson);
const option = {
legend: {
show: true,
top: 15
},
tooltip: {
trigger: 'item',
formatter: (params) => {
if (params.componentType === 'series') {
if (params.seriesType === 'scatter') {
return `${params.data.name}<br/>数值: ${params.data.value[2]}`;
} else {
return `${params.name}<br/>数值: ${params.value[2] || 0}`;
}
}
return params.name;
}
},
geo: {
map: 'china',
roam: true,
zoom: 1,
label: {
emphasis: {
show: true,
color: '#fff'
}
},
itemStyle: {
areaColor: '#F9FAFC',
borderColor: '#E7F1FF',
borderWidth: 1
},
emphasis: {
itemStyle: {
areaColor: '#ffd700'
},
label: {
show: true,
color: '#fff',
fontSize: 12
}
}
},
series: [
// 地图系列 - 用于省份高亮
{
name: '',
type: 'map',
map: 'china',
geoIndex: 0,
data: mapData.map(item => ({
name: item.name,
value: item.value,
itemStyle: {
// color: getColorByValue(item.value, colorRanges),
areaColor: '#E7F1FF'
}
})),
emphasis: {
itemStyle: {
areaColor: '#ffd700',
borderColor: '#333',
borderWidth: 2
},
label: {
show: true,
fontSize: 14,
fontWeight: 'bold',
color: '#333'
}
}
},
// 散点系列 - 用于显示圆点数字标记
{
name: mapData[0].name,
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'circle',
symbolSize: 10,
itemStyle: {
color: 'rgba(5, 95, 194, 1)',
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.5)'
},
data: mapData[0].data.map(item => ({
name: item.name,
value: [item.coord[0], item.coord[1], item.value],
itemStyle: {
color: 'rgba(5, 95, 194, 1)'
}
})),
// data: mapData[0].data,
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
},
itemStyle: {
shadowBlur: 20,
shadowColor: 'rgba(0, 0, 0, 0.8)'
}
}
},
{
name: mapData[1].name,
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'circle',
symbolSize: 10,
itemStyle: {
color: 'rgba(250, 140, 22, 1)',
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.5)'
},
data: mapData[1].data.map(item => ({
name: item.name,
value: [item.coord[0], item.coord[1], item.value],
itemStyle: {
color: 'rgba(250, 140, 22, 1)'
}
})),
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
},
itemStyle: {
shadowBlur: 20,
shadowColor: 'rgba(0, 0, 0, 0.8)'
}
}
},
{
name: mapData[2].name,
type: 'scatter',
coordinateSystem: 'geo',
symbol: 'circle',
symbolSize: 10,
itemStyle: {
color: 'rgba(114, 46, 209, 1)',
shadowBlur: 10,
shadowColor: 'rgba(0, 0, 0, 0.5)'
},
data: mapData[2].data.map(item => ({
name: item.name,
value: [item.coord[0], item.coord[1], item.value],
itemStyle: {
color: 'rgba(114, 46, 209, 1)'
}
})),
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
},
itemStyle: {
shadowBlur: 20,
shadowColor: 'rgba(0, 0, 0, 0.8)'
}
}
}
]
};
return option
}
export default getMapChart
\ No newline at end of file
const getRadarChart = () => {
const indicators = [
{ name: "集成电路", max: 10 },
{ name: "能源领域", max: 10 },
{ name: "量子科技", max: 10 },
{ name: "通信网络", max: 10 },
{ name: "人工智能", max: 10 },
{ name: "生物科技", max: 10 }
];
const data337 = [9, 6, 6, 6, 9, 7];
const data301 = [5, 3, 7, 8, 7, 9];
const data232 = [4, 10, 3, 4, 2, 5];
const option = {
color: ["rgba(5, 95, 194, 1)", "rgba(250, 140, 22, 1)", "rgba(146, 84, 222, 1)"],
legend: {
top: 8,
left: 30,
icon: "circle",
itemWidth: 12,
itemHeight: 12,
itemGap: 24,
textStyle: {
color: "rgb(95, 101, 108)",
fontSize: 16,
fontFamily: "Microsoft YaHei",
fontWeight: 400,
lineHeight: 24
},
data: ["337调查", "301调查", "232调查"]
},
radar: {
shape: "polygon",
splitNumber: 5,
indicator: indicators,
center: ["50%", "56%"],
radius: "58%",
startAngle: 90,
clockwise: false,
axisName: {
color: "rgba(59, 65, 75, 1)",
fontSize: 16,
fontFamily: "Microsoft YaHei",
fontWeight: 700,
lineHeight: 24,
padding: [0, 5]
},
splitLine: {
lineStyle: {
color: "#d0d0d0",
width: 1
}
},
axisLine: {
lineStyle: {
color: "#d0d0d0",
width: 1
}
},
splitArea: {
show: true,
areaStyle: {
color: ["#fff", "rgb(247, 248, 249)", "#fff", "rgb(247, 248, 249)", "#fff"]
}
}
},
series: [
{
name: "337调查",
type: "radar",
data: [{ value: data337 }],
lineStyle: {
width: 2,
color: "rgba(5, 95, 194,1)"
},
symbol: "none",
areaStyle: {
color: "rgba(5, 95, 194,0.15)"
}
},
{
name: "301调查",
type: "radar",
data: [{ value: data301 }],
lineStyle: {
width: 2,
color: "rgba(250, 140, 22, 1)"
},
symbol: "none",
areaStyle: {
color: "rgba(250, 140, 22, 0.15)"
}
},
{
name: "232调查",
type: "radar",
data: [{ value: data232 }],
lineStyle: {
width: 2,
color: "rgba(146, 84, 222, 1)"
},
symbol: "none",
areaStyle: {
color: "rgba(146, 84, 222, 0.15)"
}
},
]
};
return option
}
export default getRadarChart
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论