提交 b06000c9 authored 作者: coderBryanFu's avatar coderBryanFu

update

<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.000000" height="16.000000" fill="none" customFrame="#000000">
<rect id="arrow-up" width="16.000000" height="16.000000" x="0.000000" y="0.000000" />
<path id="Union" d="M7.33343 13.0027L7.33343 5.27885L4.33343 8.27885L3.39062 7.33604L8.0001 2.72656L12.6096 7.33604L11.6668 8.27885L8.66677 5.27885L8.66677 13.0027L7.33343 13.0027Z" fill="rgb(248,52,52)" fill-rule="evenodd" />
</svg>
......@@ -17,9 +17,13 @@
<div class="nav-menu">
<el-dropdown @command="handleHomeCommand" class="home-dropdown">
<div class="nav-link dropdown-trigger">
<el-icon><House /></el-icon>
<el-icon>
<House />
</el-icon>
<span>首页</span>
<el-icon class="dropdown-arrow"><ArrowDown /></el-icon>
<el-icon class="dropdown-arrow">
<ArrowDown />
</el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
......@@ -33,19 +37,27 @@
</template>
</el-dropdown>
<div class="nav-link">
<el-icon><User /></el-icon>
<el-icon>
<User />
</el-icon>
<span>国家</span>
</div>
<div class="nav-link">
<el-icon><Location /></el-icon>
<el-icon>
<Location />
</el-icon>
<span>领域</span>
</div>
<div class="nav-link">
<el-icon><Document /></el-icon>
<el-icon>
<Document />
</el-icon>
<span>要素</span>
</div>
<div class="nav-link">
<el-icon><Bell /></el-icon>
<el-icon>
<Bell />
</el-icon>
<span>事件</span>
</div>
</div>
......@@ -158,15 +170,18 @@ body {
height: 984px;
position: relative;
}
.nav-brand {
display: flex;
align-items: center;
gap: 12px;
position: absolute;
left: 160px;
.brand-icon {
width: 48px;
height: 48px;
img {
width: 100%;
height: 100%;
......@@ -188,6 +203,7 @@ body {
font-weight: 700;
line-height: 42px;
}
.text-en {
color: rgba(10, 18, 30, 1);
font-family: Microsoft YaHei;
......@@ -249,22 +265,27 @@ body {
color: #333;
position: absolute;
right: 159px;
.email {
width: 20px;
height: 20px;
img {
width: 100%;
height: 100%;
}
}
.avator {
width: 32px;
height: 32px;
img {
width: 100%;
height: 100%;
}
}
.user {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
......@@ -276,19 +297,23 @@ body {
.wrapper {
position: relative;
.ai-btn {
position: absolute;
top: 50%;
right: 46px;
cursor: pointer;
.icon {
width: 96px;
height: 96px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 24px;
color: rgba(59, 65, 75, 1);
......@@ -299,6 +324,7 @@ body {
text-align: center;
}
}
.ai-dialog {
position: absolute;
right: 100px;
......@@ -317,6 +343,7 @@ body {
.el-main {
padding: 0;
height: calc(100vh - 96px);
overflow: hidden;
background-color: rgba(246, 251, 255, 1);
}
</style>
/* 声明字体 */
@font-face {
font-family: "YouSheBiaoTiHei";
src: url("./YouSheBiaoTiHei.ttf") format("truetype");
font-weight: normal;
font-style: normal;
font-display: swap; /* 性能优化:先显示备用字体 */
}
/* 全局一次性应用(可选) */
body {
font-family: "YouSheBiaoTiHei", sans-serif;
}
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.000000" height="16.000000" fill="none" customFrame="#000000">
<rect id="form-filled" width="16.000000" height="16.000000" x="0.000000" y="0.000000" />
<path id="Union" d="M14.6667 1.33594L1.33337 1.33594L1.33337 4.66927L14.6667 4.66927L14.6667 1.33594ZM14.6667 6.0026L1.33337 6.0026L1.33337 14.6693L14.6667 14.6693L14.6667 6.0026ZM12 8.33594L12 9.66927L4.00004 9.66927L4.00004 8.33594L12 8.33594ZM9.33337 11.0026L9.33337 12.3359L4.00004 12.3359L4.00004 11.0026L9.33337 11.0026Z" fill="rgb(5,95,194)" fill-opacity="0.800000012" fill-rule="evenodd" />
</svg>
<template>
<div class="policy-tracker-container">
<PolicyOverview />
<!-- 顶部搜索栏 -->
<div class="top-search-bar" v-if="props.showSearch">
<div class="search-left">
......@@ -80,6 +81,7 @@ import { Search } from '@element-plus/icons-vue';
import PolicyList from './PolicyList.vue';
import CardTitle from './CardTitle.vue';
import { getOverviewPolicy } from '@/api'
import PolicyOverview from '@/views/thinkTank/components/PolicyOverview.vue'
const props = defineProps({
showSearch: {
......
......@@ -9,6 +9,7 @@ import { withFallbackImage } from "./utils";
import "./styles/scrollbar.css";
import "./styles/elui.css";
import "./styles/main.css";
import '@/assets/fonts/font.css'
const app = createApp(App);
......
......@@ -2,6 +2,8 @@ import { createRouter, createWebHistory } from "vue-router";
//中美博弈概览
import overView from "@/views/overView/index.vue";
//新闻速览
import newsBrief from "@/views/newsBrief/index.vue"
// 智库相关
import thinkTank from "../views/thinkTank/index.vue";
import ThinkTankDetail from "@/views/thinkTank/ThinkTankDetail/index.vue";
......@@ -80,10 +82,18 @@ const routes = [
name: "overView",
component: overView,
meta: {
title: "法案首页"
title: "中美博弈概览"
}
},
//新闻速览页面路由
{
path: "/newsBrief",
name: "newsBrief",
component: newsBrief,
meta: {
title: "新闻速览"
}
},
// 智库系统的主要路由
{
path: "/thinkTank",
......
<template>
<div class="header-btn" style="width: 100px;display: flex;" @click="back">
<img :src="`src/assets/icons/arrow-left.png`" style="width: 24px;height: 24px;" /> 返回
</div>
<div style="width: 100%;height: 100%;padding:0 20% ">
<div>
<div class=" news-header" style="text-align: left;">
今日要闻
</div>
<div class="content" style="margin-bottom: 20px;">
基于情报价值评估预测算法,掌握全球重要潜在动向
</div>
</div>
<div class="box" style="width: 100%;height: 90%;">
<div class="box-header" style="height: 5vh;">
<div style="display: flex; justify-content: center; ">
<div v-for="item in btnList" :class="btnSelect !== item ? 'header-btn-gray' : 'header-btn-select'"
@click="changeBtn(item)">
{{ item }} >
</div>
</div>
</div>
<div class="divider"></div>
<div v-for="item in HeadlinesData">
<div style="display: flex;">
<div>
<div class="title-blob">
{{ item.title }}
</div>
<div class="content">
新闻来源: {{ item.from }} 发表时间:{{ item.time }}
</div>
<div style="display: flex;">
<div v-for="tag in item.tag" class="tag">
{{ tag }}
</div>
</div>
</div>
<div style="margin-left: auto;padding: 10px;">
<img :src="item.image" />
</div>
</div>
<div class="divider">
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
const btnList = ref(["全部", "军事", "政治", "经济", "敌我"])
const btnSelect = ref('新闻纵览')
const HeadlinesData = ref([
{
"title": "黎巴嫩真主党指责美国破坏黎稳定 谴责以色列“蓄意挑衅”",
"from": "人民网",
"time": "2025-10-05",
"tag": ["以色列", "美国"],
"image": '/testData/HeadlinesData-img.png',
},
{
"title": "IMF上调中东和北非地区经济增长预期",
"from": "CNN",
"time": "2025-10-05",
"tag": ["经济", "中东", "IMF"],
"image": '/testData/HeadlinesData-img.png',
},
{
"title": "日本外务省亚洲大洋洲局局长金井正彰启程访华 预计18日与中方会面",
"from": "人民网",
"time": "2025-10-05",
"tag": ["日本", "访华"], "image": '/testData/HeadlinesData-img.png',
},
{
"title": "韩日因独岛主权争议暂停本月联合搜救演习",
"from": "凤凰网",
"time": "2025-10-05",
"tag": ["独岛", "联合军演", "韩国", "日本"], "image": '/testData/HeadlinesData-img.png',
},
{
"title": "美“福特”号航母抵达加勒比海 于委内瑞拉附近展开大规模军事集结",
"from": "央视网",
"time": "2025-10-05",
"tag": ["美国", "航母", "加勒比海"], "image": '/testData/HeadlinesData-img.png',
}
])
function changeBtn(btn) {
btnSelect.value = btn
}
const emit = defineEmits(["back"]);
function back() {
emit('back', 'home')
}
</script>
<style scoped>
@import url('./style.css');
.newsBrief-page {
max-width: 100vw;
height: 100%;
overflow: hidden;
margin: 0 auto;
padding: 5vh 10vw 20vh 10vw;
background: url('@/assets/images/background.png') no-repeat;
background-position: center -100px;
background-size: 100% 100%;
min-height: 100vh;
}
</style>
<template>
<div class="header-btn" style="width: 100px;display: flex;" @click="back">
<img :src="`src/assets/icons/arrow-left.png`" style="width: 24px;height: 24px;" /> 返回
</div>
<div style="width: 100%;height: 100%;padding:0 20% ">
<div>
<div class=" news-header" style="text-align: left;">
中美博弈专题
</div>
<div class="content" style="margin-bottom: 20px;">
汇聚全球资讯,呈现全球动态,掌握时事脉搏
</div>
</div>
<div class="box" style="width: 100%;height: 90%;">
<div class="box-header" style="height: 5vh;">
<div style="display: flex; justify-content: center; ">
<div v-for="item in btnList" :class="btnSelect !== item ? 'header-btn-gray' : 'header-btn-select'"
@click="changeBtn(item)">
{{ item }} >
</div>
</div>
</div>
<div class="divider"></div>
<div v-for="item in HeadlinesData">
<div style="display: flex;">
<div>
<div class="title-blob">
{{ item.title }}
</div>
<div class="content">
新闻来源: {{ item.from }} 发表时间:{{ item.time }}
</div>
<div style="display: flex;">
<div v-for="tag in item.tag" class="tag">
{{ tag }}
</div>
</div>
</div>
<div style="margin-left: auto;padding: 10px;">
<img :src="`src/assets/icons/arrow-${item.arrow}.png`" />
</div>
</div>
<div class="divider">
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
// const props = defineProps({
// type: {
// type: String,
// default: 'home'
// }
// })
const btnList = ref(["全部", "军事", "政治", "经济", "敌我"])
const btnSelect = ref('新闻纵览')
const HeadlinesData = ref([
{
"title": "黎巴嫩真主党指责美国破坏黎稳定 谴责以色列“蓄意挑衅”",
"from": "人民网",
"time": "2025-10-05",
"tag": ["以色列", "美国"],
"arrow": '0',
},
{
"title": "IMF上调中东和北非地区经济增长预期",
"from": "CNN",
"time": "2025-10-05",
"tag": ["经济", "中东", "IMF"],
"arrow": '1',
},
{
"title": "日本外务省亚洲大洋洲局局长金井正彰启程访华 预计18日与中方会面",
"from": "人民网",
"time": "2025-10-05",
"tag": ["日本", "访华"],
"arrow": '1',
},
{
"title": "韩日因独岛主权争议暂停本月联合搜救演习",
"from": "凤凰网",
"time": "2025-10-05",
"tag": ["独岛", "联合军演", "韩国", "日本"],
"arrow": '0',
},
{
"title": "美“福特”号航母抵达加勒比海 于委内瑞拉附近展开大规模军事集结",
"from": "央视网",
"time": "2025-10-05",
"tag": ["美国", "航母", "加勒比海"],
"arrow": '0',
}
])
function changeBtn(btn) {
btnSelect.value = btn
}
const emit = defineEmits(["back"]);
function back() {
emit('back', 'home')
}
</script>
<style scoped>
@import url('./style.css');
.newsBrief-page {
max-width: 100vw;
height: 100%;
overflow: hidden;
margin: 0 auto;
padding: 5vh 10vw 20vh 10vw;
background: url('@/assets/images/background.png') no-repeat;
background-position: center -100px;
background-size: 100% 100%;
min-height: 100vh;
}
</style>
<template>
<div class="newsBrief-page">
<div v-if="showPage === 'home'">
<div style="justify-content: space-between;">
<div class="news-header">
新闻速览
</div>
<div style="display: flex;padding: 3vh;justify-content: center; ">
<el-input placeholder="请输入关键词" :suffix-icon="searchInput" clearable style="width: 60vw;height: 5vh;">
</el-input>
</div>
<div style="display: flex;padding: 3vh;justify-content: center; ">
<div v-for="item in btnList" :class="btnSelect !== item ? 'header-btn' : 'header-btn-select'"
@click="changeBtn(item)">
{{ item }} >
</div>
<div class="header-btn-more">
<img src="@/assets/icons/adjustment.png" />
</div>
</div>
</div>
<div style="display: flex;">
<div class="box">
<div class="box-header">
<img class="box-header-img" src="@/assets/icons/Headlines-icon.svg"></img>
<div style="cursor: pointer;" @click="changePage('headlines')">
今日要闻 >
</div>
</div>
<div class="divider"></div>
<div v-for="item in HeadlinesData">
<div style="display: flex;">
<div>
<div class="title-blob">
{{ item.title }}
</div>
<div class="content">
新闻来源: {{ item.from }} 发表时间:{{ item.time }}
</div>
<div style="display: flex;">
<div v-for="tag in item.tag" class="tag">
{{ tag }}
</div>
</div>
</div>
<div style="margin-left: auto;padding: 10px;">
<img :src="item.image" />
</div>
</div>
<div class="divider">
</div>
</div>
</div>
<div class="box" style=" margin-left: 4%;">
<div class="box-header">
<img class="box-header-img" src="@/assets/icons/subject-icon.png"></img>
<div style="cursor: pointer;" @click="changePage('subject')">
中美博弈专题
</div>
</div>
<div class="divider">
</div>
<div v-for="(item, index) in subjectData">
<div class="subject-line">
<!-- 左侧:序号 + 文字 -->
<div style="display: flex; align-items: center;">
<div :style="{
color:
index === 0 ? '#CF4F51'
: index === 1 ? '#FF964D'
: index === 2 ? '#E8BD0D'
: '#3B414B'
}">
{{ index <= 2 ? index + 1 : "." }} </div>
<div
style="white-space: nowrap;overflow: hidden;text-overflow: ellipsis;width: 32vw ;margin-left: 20px;"
:class="index <= 2 ? 'title-blob' : 'content'">{{ item.text }}
</div>
</div>
<!-- 右侧:箭头 -->
<img :src="`src/assets/icons/arrow-${item.arrow}.png`" />
</div>
</div>
</div>
</div>
</div>
<Headlines v-if="showPage === 'headlines'" @type="showPage" @back="changePage" />
<Subject v-if="showPage === 'subject'" @back="changePage" />
</div>
</template>
<script setup>
import { ref } from "vue";
import Headlines from './Headlines.vue'
import Subject from './Subject.vue'
// import style from './style.css'
//顶部数据搜索
const searchInput = ref('')
const btnList = ref(["新闻纵览", "焦点新闻", "全球热点", "军事热点", "台湾动向", "美国政治", "亚洲局势", "东亚动态"])
const btnSelect = ref('新闻纵览')
const HeadlinesData = ref([
{
"title": "黎巴嫩真主党指责美国破坏黎稳定 谴责以色列“蓄意挑衅”",
"from": "人民网",
"time": "2025-10-05",
"tag": ["以色列", "美国"],
"image": '/testData/HeadlinesData-img.png',
},
{
"title": "IMF上调中东和北非地区经济增长预期",
"from": "CNN",
"time": "2025-10-05",
"tag": ["经济", "中东", "IMF"],
"image": '/testData/HeadlinesData-img.png',
},
{
"title": "日本外务省亚洲大洋洲局局长金井正彰启程访华 预计18日与中方会面",
"from": "人民网",
"time": "2025-10-05",
"tag": ["日本", "访华"], "image": '/testData/HeadlinesData-img.png',
},
{
"title": "韩日因独岛主权争议暂停本月联合搜救演习",
"from": "凤凰网",
"time": "2025-10-05",
"tag": ["独岛", "联合军演", "韩国", "日本"], "image": '/testData/HeadlinesData-img.png',
},
{
"title": "美“福特”号航母抵达加勒比海 于委内瑞拉附近展开大规模军事集结",
"from": "央视网",
"time": "2025-10-05",
"tag": ["美国", "航母", "加勒比海"], "image": '/testData/HeadlinesData-img.png',
}
])
function changeBtn(btn) {
btnSelect.value = btn
}
//当前页面显示
const showPage = ref('home')
function changePage(page) {
console.log(page)
showPage.value = page
}
//博弈专题新闻数据
const subjectData = ref([
{ id: 1, text: "乌克兰与法国签署意向书 将获 100 架“阵风”战机及多套防空系统", arrow: 0 },
{ id: 2, text: "安理会通过涉加沙决议 建立和平委员会作为过渡行政机构", arrow: 1 },
{ id: 3, text: "日本首相高市早苗涉台及修“无核三原则”言论遭多方强烈反对", arrow: 1 },
{ id: 4, text: "美“福特”号航母打击群进入加勒比海 委方谴责其意图策动政权更迭", arrow: 1 },
{ id: 5, text: "BBC回应特朗普10亿-50亿美元索赔诉讼 称诽谤指控无依据", arrow: 1 },
{ id: 6, text: "俄军打击乌142个区域设施 乌军击落或压制91架俄无人机", arrow: 1 },
{ id: 7, text: "中国女法官张玲玲以第一高票当选联合国上诉法庭法官", arrow: 0 },
{ id: 8, text: "美股三大股指17日收盘普跌 比特币跌破92000美元", arrow: 1 },
{ id: 9, text: "高盛大幅下调2026年布伦特和WTI原油价格预测", arrow: 1 },
{ id: 10, text: "2026米兰冬奥会火炬传递完整路线公布 将穿越意大利全部20个大区", arrow: 1 },
{ id: 11, text: "特朗普宣称若重掌白宫将推动美国开展自1992年以来首次核试验", arrow: 1 },
{ id: 12, text: "欧盟发布2025年秋季经济预测 欧元区今年GDP预计增长1.3%", arrow: 1 }
])
</script>
<style scoped>
@import url('./style.css');
.newsBrief-page {
max-width: 100vw;
height: 100%;
overflow: hidden;
margin: 0 auto;
padding: 5vh 10vw 20vh 10vw;
background: url('@/assets/images/background.png') no-repeat;
background-position: center -100px;
background-size: 100% 100%;
min-height: 100vh;
}
</style>
/* 分割线 */
/* 左右横线 + 中间文字 */
.news-header {
color: rgba(34, 41, 52, 1);
font-family: "YouSheBiaoTiHei", sans-serif;
font-size: 46px;
font-weight: 400;
line-height: 60px;
letter-spacing: 0px;
text-align: center;
}
.header-btn {
cursor: pointer;
padding: 2px 20px;
box-sizing: border-box;
margin: 5px;
border: 1px solid rgba(255, 255, 255, 1);
border-radius: 32px;
background: rgba(255, 255, 255, 0.8);
color: rgba(95, 101, 108, 1);
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: center;
}
.header-btn-gray {
cursor: pointer;
padding: 2px 20px;
box-sizing: border-box;
margin: 5px;
border: 1px solid rgba(32, 33, 35, 0.07);
border-radius: 32px;
background: rgba(32, 33, 35, 0.07);
color: rgba(95, 101, 108, 1);
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: center;
}
.header-btn-select {
cursor: pointer;
padding: 2px 20px;
margin: 5px;
box-sizing: border-box;
border: 1px solid rgba(174, 214, 255, 1);
border-radius: 32px;
background: rgba(231, 243, 255, 1);
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: center;
}
.header-btn-more {
cursor: pointer;
width: 34px;
height: 34px;
margin: 5px;
box-sizing: border-box;
border: 1px solid, rgba(255, 255, 255, 1);
border-radius: 32px;
background: rgba(255, 255, 255, 0.8);
display: flex; /* 开启 flex */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.box {
width: 48%;
height: 55vh;
box-sizing: border-box;
border: 1px solid rgba(231, 243, 255, 1);
border-radius: 10px;
background: rgba(255, 255, 255, 0.8);
padding: 1vw;
.box-header {
height: 4vh;
display: flex;
text-align: left;
font-size: 24px;
font-weight: 700;
align-items: center;
.box-header-img {
height: 24px;
width: 24px;
margin: 0 5px;
}
}
.title-blob {
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: left;
}
.tag {
margin: 2px;
padding: 2px 8px 2px 8px;
border-radius: 4px;
background: rgba(223, 226, 231, 0.41);
color: rgba(132, 136, 142, 1);
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
}
}
.content {
color: rgba(132, 136, 142, 1);
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
}
.divider {
width: 100%;
height: 1px;
background: #eaecee;
}
.subject-line {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 2.7vh;
margin: 1vh 0;
}
<template>
<div class="home-wrapper">
<div class="home-main">
<div class="home-main-center">
<div class="center-center">
<div class="center-header">
<div class="center-header-left">
<img class="iconstyle" src="./assets/images/warning.png" ></img>
<div class="center-header-title">风险信号管理</div>
</div>
<div class="center-header-right">
<img class="img" src="./assets/images/danger.png"></img>
<div class="text">风险统计</div>
</div>
</div>
<div class="center-middle">
<div class="center-middle-left">
<div class="lineitem">
<div class="item">
<div class="top">
<div class="dot" style="background-color: rgba(95, 101, 108, 1);"></div>
<div class="text1">本年新增风险</div>
</div>
<div class="text2" style="color: rgba(95, 101, 108, 1);">219项</div>
</div>
<div class="item">
<div class="top">
<div class="dot" style="background-color: rgba(95, 101, 108, 1);"></div>
<div class="text1">本月新增风险</div>
</div>
<div class="text2" style="color: rgba(95, 101, 108, 1);">40项</div>
</div>
</div>
<div class="lineitem">
<div class="item">
<div class="top">
<div class="dot" style="background-color: rgba(5, 95, 194, 1);"></div>
<div class="text1">已处理风险</div>
</div>
<div class="text2" style="color: rgba(5, 95, 194, 1);">212项</div>
</div>
<div class="item">
<div class="top">
<div class="dot" style="background-color: rgba(206, 79, 81, 1);"></div>
<div class="text1">待处理风险</div>
</div>
<div class="text2" style="color: rgba(206, 79, 81, 1);">7项</div>
</div>
</div>
</div>
<div class="center-middle-right" id="chartCalendar"></div>
</div>
</div>
</div>
<div class="home-main-footer">
<div class="home-main-footer-main">
<div class="left">
<div class="left-box1">
<div class="left-box1-header">
<div class="icon"></div>
<div class="title">{{ "风险类型" }}</div>
</div>
<div class="left-box1-main">
<div
class="time-label"
v-for="(item, index) in riskType"
:key="index"
>
<el-checkbox
v-model="item.selected"
:label="item.name"
size="large"
/>
</div>
</div>
</div>
<div class="left-box1">
<div class="left-box1-header">
<div class="icon"></div>
<div class="title">{{ "风险来源" }}</div>
</div>
<div class="left-box1-main">
<div
class="time-label"
v-for="(item, index) in riskSource"
:key="index"
>
<el-checkbox
v-model="item.selected"
:label="item.name"
size="large"
/>
</div>
</div>
</div>
<div class="left-box1">
<div class="left-box1-header">
<div class="icon"></div>
<div class="title">{{ "风险等级" }}</div>
</div>
<div class="left-box1-main">
<div
class="time-label"
v-for="(item, index) in riskDegree"
:key="index"
>
<el-checkbox
v-model="item.selected"
:label="item.name"
size="large"
/>
</div>
</div>
</div>
<div class="left-box1">
<div class="left-box1-header">
<div class="icon"></div>
<div class="title">{{ "设计领域" }}</div>
</div>
<div class="left-box1-main">
<div
class="time-label"
v-for="(item, index) in area"
:key="index"
>
<el-checkbox
v-model="item.selected"
:label="item.name"
size="large"
/>
</div>
</div>
</div>
</div>
<div class="right">
<div class="right-header">
<div class="header-left">
<div class="btn-left" :class="{ btnleftactive: activeBtn === '全部' }"
@click="handleClickBtn('全部')">
<div class="btn-text" :class="{ btntextactive: activeBtn === '全部' }">全部</div>
</div>
<div class="btn-left" :class="{btnleftactive: activeBtn === '未处理'}"
@click="handleClickBtn('未处理')">
<div class="btn-text" :class="{btntextactive: activeBtn === '未处理'}">未处理</div>
</div>
<div class="btn-left" :class="{btnleftactive: activeBtn === '已处理'}"
@click="handleClickBtn('已处理')">
<div class="btn-text" :class="{btntextactive: activeBtn === '已处理'}">已处理</div>
</div>
</div>
<div class="header-right">
<div class="searchbox">
<el-input
v-model="input"
style="width: 268px; height: 100%"
placeholder="搜索"/>
<div class="search-btn"></div>
</div>
<div class="select-box">
<el-select
v-model="releaseTime"
placeholder="发布时间"
style="width: 120px"
>
<el-option
v-for="item in releaseTimeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
</div>
<div class="right-main">
<div class="itemlist" v-for="(val, idx) in riskList" :key="idx">
<div class="item-box">
<div class="box-title">
<div class="risktitle">{{ val.title }}</div>
<div class="risktype" :style="{backgroundColor: val.bgcolor,color: val.textcolor}">{{ val.risktype }}</div>
</div>
<div class="box-source">
<img class="source-pic" :src="val.pic" alt="" />
<div class="source-text">{{ val.origin }}</div>
<div class="source-text">{{ val.time }}</div>
</div>
<div class="desc-box">{{ val.dsc }}</div>
<div class="tag-box" >
<el-tag v-for="tag in val.tag">{{ tag }}</el-tag>
</div>
</div>
<div class="splitline"></div>
</div>
</div>
<div class="right-footer">
<div class="footer-left">
{{ "共105项调查" }}
</div>
<div class="footer-right">
<el-pagination
background
layout="prev, pager, next"
:total="105"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from "vue";
import * as echarts from "echarts";
import router from "@/router";
import getCalendarHeatChart from "./utils/cleandarHeat";
const activeBtn = ref("全部");
const handleClickBtn = name => {
activeBtn.value = name;
};
const riskType = ref([
{
name: "科技法案",
selected: true,
},
{
name: "行政令",
selected: true,
},
{
name: "智库报告",
selected: true,
},
{
name: "出口管制",
selected: true,
},
{
name: "投融资限制",
selected: true,
},
{
name: "市场准入限制",
selected: true,
},
{
name: "规则限制",
selected: true,
},
]);
const riskSource = ref([
{
name: "美国",
selected: true,
},
{
name: "欧盟",
selected: true,
},
{
name: "日本",
selected: true,
},
{
name: "韩国",
selected: true,
},
]);
const riskDegree = ref([
{
name: "特别重大风险",
selected: true,
},
{
name: "重大风险",
selected: true,
},
{
name: "较大风险",
selected: true,
},
{
name: "一般风险",
selected: true,
},
{
name: "无风险",
selected: true,
}
]);
const area = ref([
{
name: "人工智能",
selected: true,
},
{
name: "集成电路",
selected: true,
},
{
name: "通信网络",
selected: true,
},
{
name: "量子科技",
selected: true,
},
{
name: "生物科技",
selected: true,
},
{
name: "能源",
selected: true,
},
{
name: "航空航天",
selected: true,
},
{
name: "先进制造",
selected: true,
},
]);
const releaseTime = ref("发布时间");
const releaseTimeList = ref([
{
label: "近半年发布",
value: "近半年发布",
},
{
label: "近一年发布",
value: "近一年发布",
},
{
label: "近两年发布",
value: "近两年发布",
},
{
label: "近三年发布",
value: "近三年发布",
},
{
label: "近五年发布",
value: "近五年发布",
},
]);
const riskList = ref([
{
title: "扩大实体清单制裁范围,对中企子公司实施同等管制",
origin: "美国商务部 · 实体清单",
time:"2025年11月10日 16:14",
dsc: "任何被列入美国出口管制“实体清单”或“军事最终用户清单”的企业,如果其直接或间接持有另一家公司 ​50%或以上的股权,那么这家被控股的公司也将自动受到与清单上母公司同等的出口管制限制",
tag:["生物科技","人工智能"],
risktype: "·特别重大风险",
pic: "src/views/riskSignal/assets/images/origin1.png",
textcolor:"rgba(206, 79, 81, 1)",
bgcolor:"rgba(206, 79, 81, 0.1)"
},
{
title: "大而美法案通过国会众议院投票,将提交至总统签署",
origin: "美国国会 · 科技法案",
time:"2025年11月10日 16:14",
dsc: "",
tag:["能源","人工智能"],
risktype: "·重大风险",
pic: "src/views/riskSignal/assets/images/origin2.png",
textcolor:"rgba(255, 149, 77, 1)",
bgcolor:"rgba(255, 149, 77, 0.1)"
},
{
title: "兰德公司发布智库报告《中美经济竞争:复杂经济和地缘政治关系中的收益和风险》",
origin: "兰德公司 · 科技智库",
time:"2025年11月10日 16:14",
dsc: "包括经济竞争在内的美中竞争自2017年以来一直在定义美国外交政策。这两个经济体是世界上第一和第二大国家经济体,并且深深交织在一起。改变关系,无论多么必要,可能是昂贵的。因此,美国面临着一项挑战,确保其经济在耦合的战略竞争条件下满足国家的需求。",
tag:["生物科技","人工智能","集成电路"],
risktype: "·一般风险",
pic: "src/views/riskSignal/assets/images/origin3.png",
textcolor:"rgba(5, 95, 194, 1)",
bgcolor:"rgba(5, 95, 194, 0.1)"
},
{
title: "美国白宫发布总统政令《关于进一步延长TikTok执法宽限期的行政令》",
origin: "美国白宫 · 总统政令",
time:"2025年11月10日 16:14",
dsc: "再次推迟(第四次)对TikTok禁令的执法,新的宽限期截止日为2025年12月16日​。在宽限期内及对于宽限期前的行为,司法部不得强制执行​《保护美国人免受外国对手控制应用程序法》或因此处罚相关实体​(如TikTok及其分发平台)。",
tag:["人工智能"],
risktype: "·一般风险",
pic: "src/views/riskSignal/assets/images/origin2.png",
textcolor:"rgba(5, 95, 194, 1)",
bgcolor:"rgba(5, 95, 194, 0.1)"
},
{
title: "美国财政部更新《特别指定国民清单》",
origin: "美国财政部 · 特别指定国民清单",
time:"2025年11月10日 16:14",
dsc: "",
tag:["生物科技"],
risktype: "·特别重大风险",
pic: "src/views/riskSignal/assets/images/origin4.png",
textcolor:"rgba(206, 79, 81, 1)",
bgcolor:"rgba(206, 79, 81, 0.1)"
},
{
title: "美国FDA针对两家中国第三方检测机构的数据完整性问题采取行动",
origin: "美国食品药品监督管理局 · 规则限制",
time:"2025年11月10日 16:14",
dsc: "FDA因发现数据伪造或无效问题,向两家中国第三方检测公司(天津中联科技检测有限公司和苏州大学卫生与环境技术研究所)正式发出“一般信函”。",
tag:["生物科技","人工智能"],
risktype: "·特别重大风险",
pic: "src/views/riskSignal/assets/images/origin5.png",
textcolor:"rgba(206, 79, 81, 1)",
bgcolor:"rgba(206, 79, 81, 0.1)"
}
]);
// 绘制echarts图表
const setChart = (option, chartId) => {
let chartDom = document.getElementById(chartId);
chartDom.removeAttribute("_echarts_instance_");
let chart = echarts.init(chartDom);
chart.setOption(option);
return chart;
};
const calendarData = ref([
["2025-01-01", 20],
["2025-01-05", 120],
["2025-01-09", 220],
["2025-01-15", 320],
["2025-01-20", 120],
["2025-01-24", 420],
["2025-02-05", 80],
["2025-02-08", 280],
["2025-02-18", 480],
["2025-02-11", 420],
["2025-02-21", 320],
["2025-03-05", 160],
["2025-03-09", 260],
["2025-03-19", 460],
["2025-03-26", 430],
["2025-04-01", 70],
["2025-04-05", 170],
["2025-04-11", 270],
["2025-04-18", 370],
["2025-05-05", 210],
["2025-05-09", 210],
["2025-05-15", 410],
["2025-05-22", 480],
["2025-06-06", 45],
["2025-06-09", 415],
["2025-06-16", 245],
["2025-06-19", 332],
["2025-07-04", 127],
["2025-07-09", 327],
["2025-07-24", 427],
["2025-08-08", 150],
["2025-08-11", 250],
["2025-08-15", 350],
["2025-08-22", 460],
["2025-09-10", 480],
["2025-09-18", 312],
["2025-10-15", 60],
["2025-10-19", 80],
["2025-10-21", 190],
]);
onMounted(async () => {
let chartCalendar = getCalendarHeatChart(calendarData.value);
setChart(chartCalendar, "chartCalendar");
});
</script>
<style lang="scss" scoped>
:deep(.el-input__wrapper) {
box-shadow: none;
}
.home-wrapper {
.home-main {
// width: 1400px;
width: 100%;
margin: 0 auto;
background: url("./assets/images/background.png");
background-size: 100% 100%;
.home-main-center {
margin-top: 34px;
.center-center {
margin: 0 auto;
margin-top: 24px;
width: 1600px;
height: 288px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.center-header {
display: flex;
justify-content: space-between;
.center-header-left {
margin-left: 30px;
display: flex;
margin-top: 15px;
.iconstyle{
width: 27px;
height: 24px;
margin-top: 3px;
}
.center-header-title{
margin-left: 10px;
font-size: 24px;
font-weight: 700;
line-height: 32px;
}
}
.center-header-right {
margin-top: 16px;
margin-right: 59px;
width: 118px;
height: 36px;
border-radius: 6px;
background-color: rgba(5, 95, 194, 1);
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
cursor: pointer;
.img{
width: 16px;
height: 15px;
}
.text{
margin-left: 8px;
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: rgba(255, 255, 255, 1);
}
}
}
.center-middle{
display: flex;
.center-middle-left{
display: flex;
flex-direction: column;
.lineitem{
display: flex;
justify-content: space-between;
.item{
margin-left: 61px;
margin-top: 33px;
width: 111px;
height: 66px;
display: flex;
flex-direction: column;
justify-content: flex-end;
.top{
display: flex;
justify-content: flex-end;
.dot{
width: 6px;
height: 6px;
margin-top: 9px;
margin-right: 7px;
border-radius: 3px;
}
.text1{
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: rgba(59, 65, 75, 1);
text-align: right;
}
}
.text2{
font-size: 32px;
font-weight: 700;
line-height: 42px;
text-align: right;
}
}
}
}
.center-middle-right{
width: 1159px;
height: 189px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
margin: 30px auto 0;
}
}
}
}
.home-main-footer {
// width: 100%;
height: 1059px;
background: rgba(248, 249, 250, 1);
.home-main-footer-header {
width: 1600px;
height: 42px;
margin: 36px auto;
// background: orange;
display: flex;
justify-content: space-between;
.btn-box {
width: 1000px;
display: flex;
.btn {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 42px;
padding: 0 24px;
border-radius: 21px;
background: rgba(20, 89, 187, 0);
margin-right: 20px;
cursor: pointer;
&:hover {
background: rgba(20, 89, 187, 0.1);
}
}
.btnActive {
padding: 0 24px;
border-radius: 21px;
background: rgba(20, 89, 187, 1);
color: #fff;
&:hover {
color: #fff;
background: rgba(20, 89, 187, 1);
}
}
}
}
.home-main-footer-main {
width: 1600px;
margin-bottom: 30px;
// box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
// background: rgba(255, 255, 255, 1);
margin: 30px auto;
box-sizing: border-box;
// padding: 20px;
display: flex;
.left {
width: 389px;
height: 747px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.left-box1 {
margin-top: 17px;
.left-box1-header {
display: flex;
.icon {
width: 8px;
height: 16px;
margin-top: 4px;
border-radius: 2px 2px 0 0;
background: rgba(10, 87, 166, 1);
}
.title {
height: 2px;
margin-left: 17px;
color: rgba(10, 87, 166, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
}
.left-box1-main {
display: grid;
grid-template-columns: repeat(2,160px);
width: 336px;
margin-top: 10px;
margin-left: 17px;
.time-label {
height: 30px;
width: 160px;
margin-left: 8px;
}
}
}
}
.right {
margin-left: 16px;
width: 1196px;
border-radius: 4px;
box-shadow: 0px 0px 15px 0px rgba(60, 87, 126, 0.2);
background: rgba(255, 255, 255, 1);
.right-header {
height: 60px;
display: flex;
justify-content: space-between;
.header-left{
display: flex;
margin-left: 44px;
gap: 36px;
.btn-left{
display: flex;
height: 60px;
cursor: pointer;
align-items: center;
.btn-text{
font-size: 18px;
font-weight: 400;
line-height: 24px;
color: rgba(59, 65, 75, 1);
text-align: center;
}
.btntextactive{
font-weight: 700;
color: rgba(5, 95, 194, 1);
}
}
.btnleftactive{
border-bottom: 2px solid rgba(5, 95, 194, 1);
}
}
.header-right{
display: flex;
margin-right: 42px;
gap: 12px;
align-items: center;
.searchbox{
display: flex;
width: 300px;
height: 32px;
border-radius: 4px;
border: 1px solid rgba(230, 231, 232, 1);
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
.search-btn{
width: 16px;
height: 16px;
margin: 8px;
cursor: pointer;
background: url("./assets/images/search-icon.png");
}
}
.select-box {
width: 120px;
height: 32px;
box-sizing: border-box;
}
}
}
.right-main {
width: 1196px;
display: flex;
flex-direction: column;
.itemlist {
width: 1138px;
display: flex;
margin-top: 22px;
margin-left: 18px;
flex-direction: column;
.item-box{
width: 1113px;
margin-left: 25px;
display: flex;
flex-direction: column;
gap: 10px;
.box-title{
display: flex;
justify-content: space-between;
.risktitle{
font-size: 18px;
font-weight: 700;
line-height: 24px;
color: rgba(59, 65, 75, 1);
}
.risktype{
height: 28px;
border-radius: 20px;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
.box-source{
display: flex;
flex-direction: row;
align-items: center;
height: 24px;
gap: 10px;
.source-pic{
width: 16px;
height: 16px;
}
.source-text{
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: rgba(95, 101, 108, 1);
}
}
.desc-box{
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: rgba(59, 65, 75, 1);
text-align: justify;
}
.tag-box{
display: flex;
flex-direction: row;
gap: 8px;
}
}
.splitline{
margin: 16px auto;
background-color: rgba(234, 236, 238, 1);
height: 1px;
width: 1138px;
}
}
}
.right-footer {
display: flex;
// height: 60px;
// background: orange;
margin: 34px auto;
justify-content: space-between;
.footer-left {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
margin-left: 24px;
margin-top: 6px;
}
.footer-right {
margin-right: 24px;
}
}
}
}
}
}
}
</style>
\ No newline at end of file
const getCalendarHeatChart = (data) => {
const option = {
title: {
top: 30,
left: 'center',
text: `日历热力图`,
show: false
},
tooltip: {
position: 'top',
formatter: function (params) {
const date = new Date(params.data[0]);
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}<br/>数值: ${params.data[1]}`;
}
},
visualMap: {
show: false,
min: 0,
max: 500,
calculable: true,
orient: 'horizontal',
left: 'center',
top: 65,
inRange: {
color: ['rgba(231, 243, 255, 1)', 'rgba(138, 196, 255, 1)', 'rgba(5, 95, 194, 1)']
},
textStyle: {
color: 'rgba(95, 101, 108, 1)'
}
},
calendar: {
top: 24,
left: 30,
right: 30,
cellSize: ['auto', 20],
range: '2025',
splitLine: {
show:false
},
itemStyle: {
borderWidth: 0.5,
borderColor: '#ccc'
},
yearLabel: { show: true },
monthLabel: {
nameMap: 'cn'
},
dayLabel: {
nameMap: ['日', '一', '二', '三', '四', '五', '六'],
show: false,
}
},
series: {
type: 'heatmap',
coordinateSystem: 'calendar',
data: data
}
};
return option
}
export default getCalendarHeatChart
\ No newline at end of file
......@@ -184,6 +184,7 @@
import { ref, computed } from 'vue'
import { ArrowRight, Download } from '@element-plus/icons-vue'
import CardTitle from '@/components/CardTitle.vue'
import PolicyOverview from '../components/PolicyOverview.vue'
// props
const props = defineProps({
......
......@@ -77,7 +77,7 @@ const currentComponent = computed(() => {
onMounted(() => {
getThinkTankSummary({ id: route.params.id }).then(res => {
console.log(res.data);
summary.value = res.data;
summary.value = res.data || {};
});
});
</script>
......
<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
......@@ -33,7 +33,37 @@
<div class="stat-label">热点科技领域</div>
</div>
</div>
<div class="home-main-header-footer-link">
<ClickableCard text="最新动态" link="/billHome" target="_blank" />
<ClickableCard text="资讯要闻" link="/billHome" target="_blank" />
<ClickableCard text="数据总览" link="/billHome" target="_blank" />
<ClickableCard text="资源库" link="/billHome" target="_blank" />
</div>
<!-- 智库展示区域 -->
<div class="think-tanks-section">
<div v-for="tank in thinkTanks" :key="tank.id" class="think-tank-card" @click="handleClick(tank)">
<div class="tank-header">
<div class="tank-logo">
<el-image :src="$withFallbackImage(tank.logo, tank.id)" :alt="tank.name" />
</div>
<div class="tank-country">{{ tank.country }}</div>
</div>
<div class="tank-name">{{ tank.name }}</div>
<div class="tank-description" :title="tank.describe">{{ tank.describe }}</div>
<div class="tank-tags">
<el-tag v-for="tag in tank.tags" :key="tag" type="primary" size="small">
{{ tag }}
</el-tag>
</div>
</div>
<div class="view-all">
<span class="view-all-link">查看全部智库 ></span>
</div>
</div>
<DivideHeader style="margin: 30px auto" :titleText="'最新动态'"></DivideHeader>
<!-- 主要内容区域 -->
<div class="main-content">
<!-- 左侧数据分布 -->
......@@ -82,30 +112,61 @@
</el-button>
</div>
</div>
<!-- 智库展示区域 -->
<div class="think-tanks-section">
<div v-for="tank in thinkTanks" :key="tank.id" class="think-tank-card" @click="handleClick(tank)">
<div class="tank-header">
<div class="tank-logo">
<el-image :src="$withFallbackImage(tank.logo, tank.id)" :alt="tank.name" />
<DivideHeader style="margin: 30px auto" :titleText="'资讯要闻'"></DivideHeader>
<!-- 资讯要闻 -->
<div class="center-center">
<div class="box3">
<div class="box3-header">
<div class="box3-header-left">
<div class="box3-header-icon">
<img src="@/views/bill/billHome/assets/images/box3-header-icon.png" alt="" />
</div>
<div class="tank-country">{{ tank.country }}</div>
<div class="box3-header-title">{{ "新闻资讯" }}</div>
<div class="more">{{ "更多 +" }}</div>
</div>
<div class="tank-name">{{ tank.name }}</div>
<div class="tank-description" :title="tank.describe">{{ tank.describe }}</div>
<div class="tank-tags">
<el-tag v-for="tag in tank.tags" :key="tag" type="primary" size="small">
{{ tag }}
</el-tag>
</div>
<div class="box3-main">
<div class="box3-item" v-for="(news, index) in newsList" :key="index">
<div class="left">
<img :src="news.img" alt="" />
</div>
<div class="view-all">
<span class="view-all-link">查看全部智库 ></span>
<div class="right">
<div class="right-top">
<div class="title">{{ news.title }}</div>
<div class="time">{{ news.from }}</div>
</div>
<div class="right-footer">{{ news.content }}</div>
</div>
</div>
</div>
</div>
<div class="box4">
<div class="box4-header">
<div class="header-icon">
<img src="@/views/bill/billHome/assets/images/box4-header-icon.png" alt="" />
</div>
<div class="header-title">{{ "智库人物动态" }}</div>
<div class="more">{{ "更多 +" }}</div>
</div>
<div class="box4-main">
<div class="box4-main-item" v-for="(item, index) in messageList" :key="index">
<div class="left">
<img :src="item.img" alt="" />
</div>
<div class="right">
<div class="right-top">
<div class="name">{{ item.name }}</div>
<div class="time">{{ item.time }}</div>
</div>
<div class="content">{{ item.content }}</div>
</div>
</div>
</div>
</div>
</div>
<DivideHeader style="margin: 30px auto" :titleText="'数据总览'"></DivideHeader>
<DataOverview />
<DivideHeader style="margin: 30px auto" :titleText="'资源库'"></DivideHeader>
<ReportList />
</div>
</template>
......@@ -122,13 +183,79 @@ import mit from "@/assets/images/mit.png";
import itif from "@/assets/images/itif.png";
import mckinsley from "@/assets/images/mckinsey.png";
import { getThinkTankList } from "@/api";
import ClickableCard from "@/views/finance/components/link.vue";
import DivideHeader from "@/components/DivideHeader.vue";
import DataOverview from "./components/DataOverview.vue";
import News1 from "@/views/bill/billHome/assets/images/news1.png";
import News2 from "@/views/bill/billHome/assets/images/news2.png";
import News3 from "@/views/bill/billHome/assets/images/news3.png";
import News4 from "@/views/bill/billHome/assets/images/news4.png";
import News5 from "@/views/bill/billHome/assets/images/news5.png";
import Message1 from "@/views/bill/billHome/assets/images/message-icon1.png";
import Message2 from "@/views/bill/billHome/assets/images/message-icon2.png";
import Message3 from "@/views/bill/billHome/assets/images/message-icon3.png";
const router = useRouter();
const searchText = ref("");
const activeTime = ref("本月");
const worldMapRef = ref(null);
// 新闻资讯
const newsList = ref([
{
img: News1,
title: "美政府停摆仍持续,拨款法案存缺陷,但两党磋商露曙光",
content: `美国政府停摆已持续34天,距离历史上最长的停摆纪录仅差一天,参议院已先后13次尝试...`,
from: "11-4 · 华盛顿邮报"
},
{
img: News2,
title: "美参议院通过决议,要求终止特朗普全球关税政策",
content: `参议院以51票赞成、47票反对通过一项决议,旨在终止特朗普实施的全面关税政策,四名......`,
from: "11-4 · 纽约时报"
},
{
img: News3,
title: "美众院通过950亿美元对外援助法案,包含对台军援",
content: `国会众议院在4月通过了大规模对外援助法案,其中包括为“印太安全”提供资金的条款,......`,
from: "11-3 · 洛杉矶时报"
},
{
img: News4,
title: "“大而美”法案在激烈争议中通过",
content: `特朗普力推的大规模税收与支出法案在国会以微弱优势通过。该法案因大幅削减医疗补助和......`,
from: "11-3 · 今日美国"
},
{
img: News5,
title: "美政府“停摆”追平历史最长纪录,民生多领域受重创",
content: `联邦政府“停摆”进入第35天,追平历史纪录。食品救济项目资金中断,数百万低收入民......`,
from: "11-2 · ​福克斯新闻网"
}
]);
// 社交媒体
const messageList = ref([
{
img: Message1,
name: "唐纳德·特朗普",
time: "15:23 · 发布于真实社交",
content: `埃隆·马斯克在强力支持我竞选总统之前,早就知道我强烈反对‘电动汽车强制令’。这太荒谬了,这一直是我竞选活动的主要部分。电动汽车没问题,但不应该强迫每个人都拥有一辆。埃隆获得的补贴可能远远超过历史上任何一个人。如果没有补贴,埃隆可能不得不关门大吉,回到南非老家。`
},
{
img: Message2,
name: "埃隆·马斯克",
time: "14:49 · 发布于X",
content: `如果这个疯狂的支出法案获得通过,‘美国党’将在第二天成立。`
},
{
img: Message3,
name: "塞巴斯蒂安·马拉比",
time: "11:05 · 发布于X",
content: `提出特朗普政府的AI政策强调技术开放与快速应用,但可能以牺牲安全防范为代价,开启了“潘多拉魔盒”。`
}
]);
// 世界地图数据 - 各国智库数量统计
const mapData = ref([
{ name: "United States", value: 6, itemStyle: { color: "#ff4757" } },
......@@ -400,6 +527,237 @@ onMounted(() => {
background-position: center -100px;
background-size: 100% 100%;
min-height: 100vh;
.home-main-header-footer-link {
display: flex;
gap: 30px;
padding: 30px 0;
justify-content: center;
}
.center-center {
margin-top: 21px;
height: 450px;
display: flex;
.box3 {
width: 792px;
height: 450px;
box-shadow: 0px 0px 15px 0px rgba(25, 69, 130, 0.2);
background: rgba(255, 255, 255, 1);
.box3-header {
height: 48px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
margin: 0 auto;
display: flex;
justify-content: space-between;
padding: 0 20px;
position: relative;
.box3-header-left {
display: flex;
.box3-header-icon {
margin-top: 16px;
width: 19px;
height: 19px;
img {
width: 100%;
height: 100%;
}
}
.box3-header-title {
margin-top: 16px;
margin-left: 19px;
height: 22px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 22px;
}
.more {
width: 49px;
height: 24px;
position: absolute;
top: 14px;
right: 27px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
cursor: pointer;
}
}
}
.box3-main {
height: 402px;
overflow-y: auto;
overflow-x: hidden;
padding-top: 6px;
.box3-item {
display: flex;
height: 77px;
width: 749px;
margin-left: 21px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
.left {
width: 72px;
height: 48px;
margin-top: 15px;
img {
width: 100%;
height: 100%;
}
}
.right {
width: 657px;
margin-left: 20px;
.right-top {
width: 657px;
display: flex;
justify-content: space-between;
.title {
margin-top: 13px;
width: 520px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.time {
flex: 1;
text-align: right;
height: 22px;
margin-top: 19px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
.right-footer {
width: 657px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
}
.box4 {
margin-left: 20px;
width: 792px;
height: 450px;
box-shadow: 0px 0px 15px 0px rgba(25, 69, 130, 0.2);
background: rgba(255, 255, 255, 1);
.box4-header {
width: 792px;
height: 48px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex;
box-sizing: border-box;
padding-left: 22px;
position: relative;
.header-icon {
margin-top: 15px;
width: 20px;
height: 20px;
img {
width: 100%;
height: 100%;
}
}
.header-title {
margin-top: 16px;
margin-left: 18px;
height: 22px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 22px;
}
.more {
width: 49px;
height: 24px;
position: absolute;
top: 14px;
right: 27px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
cursor: pointer;
}
}
.box4-main {
height: 402px;
overflow-y: auto;
box-sizing: border-box;
padding-top: 8px;
.box4-main-item {
margin-top: 16px;
display: flex;
margin-left: 21px;
.left {
margin-top: 5px;
width: 36px;
height: 36px;
img {
width: 100%;
height: 100%;
}
}
.right {
margin-left: 10px;
width: 690px;
box-sizing: border-box;
border: 1px solid rgba(231, 243, 255, 1);
background: rgba(246, 250, 255, 1);
padding: 10px 15px;
.right-top {
display: flex;
justify-content: space-between;
.name {
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 700;
line-height: 24px;
}
.time {
height: 30px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
}
}
.content {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
}
}
}
}
}
.search-section {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论