提交 5e3760b4 authored 作者: coderBryanFu's avatar coderBryanFu

update

......@@ -4,7 +4,7 @@
<div class="policy-monitoring">
<div class="header">
<div class="section" v-for="(section, index) in sectionTab" :key="index"
:style="sections[index].length === 2 ? 'width: 350px' : 'width:503px'">
:style="sections[index].waveBall.length === 2 ? 'width: 350px' : 'width:503px'">
<img class="section-title" :src="`/public/icon/riskToday/btn-` + index + `.png`" />
<div class="stats">
<div v-for="value in sections[index].waveBall">
......@@ -365,6 +365,7 @@ onMounted(() => {
display: flex;
justify-content: left;
margin-top: 10px;
padding: 0 39px;
.waveBall-text {
color: rgba(59, 65, 75, 1);
......
<!--科技要闻-->
<template>
<div class="content-wrapper">
全领域
</div>
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
</script>
<style lang="scss" scoped>
.content-wrapper {
width: 1666px;
height: 2132px;
}
</style>
<!--科技要闻-->
<template>
<div class="content-wrapper">
全要素
</div>
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
</script>
<style lang="scss" scoped>
.content-wrapper {
width: 1666px;
height: 2132px;
}
</style>
<!--科技要闻-->
<template>
<div class="content-wrapper">
<div class="main-content">
<div class="cards-mask">
<div class="cards-container" :style="{ transform: `translateX(-${currentIndex * (307 + 16)}px)` }">
<div v-for="(card, index) in cardList" :key="index" class="government-card">
<div class="card-bg" :style="{ backgroundImage: `url(${card.icon || defaultIcon})` }"></div>
<div class="card-header">
<span class="card-title">{{ card.title }}</span>
<img :src="card.icon || defaultIcon" class="card-icon" alt="" />
</div>
<div class="card-body">
<div v-for="(stat, sIndex) in card.stats" :key="sIndex" class="stat-item">
<span class="stat-label">{{ stat.label }}</span>
<span class="stat-value">{{ stat.value }}</span>
</div>
</div>
</div>
</div>
</div>
<img :src="leftBtn" alt="" class="left-btn" @click="prev" :class="{ disabled: currentIndex === 0 }" />
<img
:src="rightBtn"
alt=""
class="right-btn"
@click="next"
:class="{ disabled: currentIndex >= cardList.length - 5 }"
/>
</div>
<div class="main-charts">
<div class="charts-title">
<div class="title-left">
<img :src="icon1" alt="" />
<span>美对华制裁措施数量趋势</span>
</div>
<div class="title-right">
<el-select v-model="fieldValue" placeholder="全部领域" class="custom-select">
<el-option label="全部领域" value="" />
</el-select>
<el-select v-model="deptValue" placeholder="全部部门" class="custom-select">
<el-option label="全部部门" value="" />
</el-select>
<el-select v-model="methodValue" placeholder="全部制裁手段" class="custom-select">
<el-option label="全部制裁手段" value="" />
</el-select>
</div>
</div>
<div class="charts-content">
<div ref="chartRef" class="chart-container"></div>
</div>
</div>
<div class="main-text">
<div class="text-item">
<div class="text-item-title">
<img :src="icon2" alt="" />
<span>美政府部门打压遏制最新动态</span>
</div>
<div class="text-item-content">
<div v-for="(item, index) in dynamicList" :key="index" class="dynamic-item">
<img :src="defaultImg" alt="" class="item-icon" />
<div class="item-right">
<div class="dynamic-item-header">
<span class="item-title">{{ item.title }}</span>
<span class="item-date">{{ item.date }} · {{ item.type }}</span>
</div>
<el-tooltip
effect="dark"
:content="item.content"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="dynamic-item-body">
{{ item.content }}
</div>
</el-tooltip>
<div class="dynamic-item-tags">
<span v-for="(tag, tIndex) in item.tags" :key="tIndex" class="tag" :class="getTagClass(tag)">
{{ tag }}
</span>
</div>
</div>
</div>
</div>
</div>
<div class="text-item">
<div class="text-item-title">
<img :src="icon3" alt="" />
<span>美政府部门联合制裁排行</span>
</div>
<div class="text-item-contentOther">
<div v-for="(rank, index) in rankingList" :key="index" class="ranking-card">
<div class="ranking-header">
<div class="header-left">
<div class="dept-icons">
<img
v-for="(dept, dIndex) in rank.depts"
:key="dIndex"
:src="defaultImg"
alt=""
class="dept-icon"
/>
</div>
<span class="dept-names">{{ rank.depts.join(" / ") }}</span>
</div>
<div class="header-right">
<span class="joint-count">{{ rank.count }}次联合制裁</span>
</div>
</div>
<div class="ranking-body">
<div v-for="(item, iIndex) in rank.items" :key="iIndex" class="ranking-item">
<div class="item-left">
<span class="item-type" :class="item.type === '法案' ? 'type-bill' : 'type-order'">{{
item.type
}}</span>
<el-tooltip
effect="dark"
:content="item.title"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<span class="item-title">{{ item.title }}</span>
</el-tooltip>
</div>
<span class="item-date">{{ item.date }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="main-bottom">
<div class="bottom-item">
<div class="bottom-item-title">
<img :src="icon4" alt="" />
<span>美政府部门对我打压遏制时间线</span>
</div>
<div class="bottom-item-select">
<div class="select-btn" :class="{ active: measureType === 'history' }" @click="measureType = 'history'">
历史举措
</div>
<div class="select-btn" :class="{ active: measureType === 'future' }" @click="measureType = 'future'">
未来举措
</div>
<el-select v-model="selectedField" placeholder="全部领域" class="field-select">
<el-option v-for="item in fieldOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
<div class="bottom-content">
<div class="timeline-container">
<div class="timeline-item">
<div ref="mainChartRef" :style="{ width: '100%', height: totalHeight + 'px' }"></div>
</div>
<div class="timelineBar">
<div ref="sliderChartRef" style="width: 100%; height: 100%"></div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
import * as echarts from "echarts";
import defaultIcon from "../../assets/defaultIcon.png";
import leftBtn from "../../assets/left-btn.png";
import rightBtn from "../../assets/right-btn.png";
import icon1 from "../../assets/icon1.png";
import icon2 from "../../assets/icon2.png";
import icon3 from "../../assets/icon3.png";
import icon4 from "../../assets/icon4.png";
import defaultImg from "../../../../assets/images/default-icon2.png";
const cardList = ref([
{
title: "联邦参议院",
stats: [
{ label: "法案(提出)", value: "132项" },
{ label: "法案(通过)", value: "9项" }
]
},
{
title: "联邦众议院",
stats: [
{ label: "法案(提出)", value: "215项" },
{ label: "法案(通过)", value: "15项" }
]
},
{
title: "商务部",
stats: [
{ label: "232调查", value: "11次" },
{ label: "政令", value: "29项" }
]
},
{
title: "财政部",
stats: [
{ label: "232调查", value: "9次" },
{ label: "涉军企业清单", value: "3次" },
{ label: "政令", value: "15项" }
]
},
{
title: "贸易代表办公室",
stats: [
{ label: "301调查", value: "4次" },
{ label: "政令", value: "21项" }
]
},
{
title: "司法部",
stats: [
{ label: "起诉案例", value: "18宗" },
{ label: "法律制裁", value: "5项" }
]
},
{
title: "国土安全部",
stats: [
{ label: "实体清单", value: "42家" },
{ label: "限制进口", value: "12项" }
]
},
{
title: "联邦调查局",
stats: [
{ label: "技术调查", value: "33次" },
{ label: "安全审查", value: "27项" }
]
}
]);
const currentIndex = ref(0);
const fieldValue = ref("");
const deptValue = ref("");
const methodValue = ref("");
const measureType = ref("history");
const selectedField = ref("all");
const fieldOptions = ref([{ label: "全部领域", value: "all" }]);
const dynamicList = ref([
{
title: "联邦参议院:通过2026财年国防授权法案",
date: "2025年12月18日",
type: "法案",
content: "2026财年国防授权法案(NDAA)已于2025年12月18日由美国总统特朗普签署成为法律,法案...",
tags: ["航空航天", "能源"]
},
{
title: "美国FDA:针对两家中国第三方检测机构的数据完整性问题采取行动",
date: "2025年12月18日",
type: "法案",
content: "FDA因发现数据伪造或无效问题,向两家中国第三方检测公司(天津中联科技检测有限公司和苏...",
tags: ["新材料", "生物科技"]
},
{
title: "美国FCC:出台电信设备市场准入认证新规",
date: "2025年12月18日",
type: "法案",
content: "将国家安全审查全面嵌入设备授权程序,对实验室资质、测试标准以及供应链设置严格限制。",
tags: ["人工智能", "集成电路"]
},
{
title: "商务部工业与安全局:对实体清单的修订",
date: "2025年12月18日",
type: "出口管制",
content: "美国商务部工业与安全局公布对中国半导体出口管制措施新规则,将140家中国半导体公司列入...",
tags: ["人工智能", "集成电路"]
},
{
title: "国际贸易委员会:外国制造的半导体器件及其下游产品和组件",
date: "2025年12月18日",
type: "市场准入限制",
content: "美国国际贸易委员会(ITC)投票决定对特定半导体器件及其下游计算产品和组件(Certain ...",
tags: ["集成电路"]
}
]);
const getTagClass = tag => {
// 1. 定义已知标签的固定颜色映射
const tagColorMap = {
航空航天: "tag-blue",
生物科技: "tag-blue",
集成电路: "tag-blue",
能源: "tag-green",
新材料: "tag-green",
人工智能: "tag-red"
};
// 2. 如果是已知标签,直接返回对应颜色
if (tagColorMap[tag]) return tagColorMap[tag];
// 3. 如果是未知标签,使用简单的字符串哈希算法分配一个稳定的颜色
const colors = ["tag-blue", "tag-green", "tag-red"];
let hash = 0;
for (let i = 0; i < tag.length; i++) {
hash = tag.charCodeAt(i) + ((hash << 5) - hash);
}
// 取绝对值并取模,确保同一个字符串永远得到同一个颜色类
return colors[Math.abs(hash) % colors.length];
};
const rankingList = ref([
{
depts: ["商务部", "财政部", "国务院"],
count: 4,
items: [
{ type: "法案", title: "大而美法案", date: "2025年12月21日" },
{ type: "政令", title: "调整互惠关税范围及建立贸易与安全协议执行程序", date: "2025年12月12日" },
{ type: "政令", title: "综合对外投资国家安全法案", date: "2025年12月7日" },
{ type: "政令", title: "推动美国人工智能技术栈的出口", date: "2025年12月4日" }
]
},
{
depts: ["国务院", "食品药品监督管理局", "商务部"],
count: 2,
items: [
{ type: "法案", title: "生物安全法案", date: "2025年12月14日" },
{ type: "政令", title: "调整关税:针对中华人民共和国合成阿片类药物供应链", date: "2025年11月24日" }
]
},
{
depts: ["商务部", "联邦通信委员会"],
count: 2,
items: [
{ type: "政令", title: "保护抖音的同时保护国家安全", date: "2025年11月9日" },
{ type: "政令", title: "赢得 6G 竞赛", date: "2025年10月27日" }
]
},
{
depts: ["贸易代表办公室", "商务部"],
count: 2,
items: [{ type: "政令", title: "第301条关于中国针对海事、物流和造船业以争取主导地位的行动", date: "2025年10月24日" }]
}
]);
const chartRef = ref(null);
let myChart = null;
const mainChartRef = ref(null);
const sliderChartRef = ref(null);
const totalHeight = ref(600);
let mainChart = null;
let sliderChart = null;
const parseDate = (str) => {
const match = str.match(/(\d+)(\d+)(\d+)日/);
if (match) return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3])).getTime();
return new Date().getTime();
};
const timelineAllData = computed(() => {
let all = [];
rankingList.value.forEach(rank => {
all = all.concat(rank.items);
});
dynamicList.value.forEach(item => {
all.push({ title: item.title, date: item.date, type: item.type });
});
return all.sort((a, b) => parseDate(b.date) - parseDate(a.date));
});
const updateTimeline = (startTime, endTime) => {
const filtered = timelineAllData.value.filter(item => {
const t = parseDate(item.date);
return t >= startTime && t <= endTime;
});
const itemHeight = 80;
totalHeight.value = Math.max(filtered.length * itemHeight, 552);
setTimeout(() => {
if (!mainChart) return;
mainChart.resize();
const option = {
grid: {
left: 150,
right: 50,
top: 20,
bottom: 20
},
tooltip: {
show: true,
formatter: (params) => {
const item = filtered[params.dataIndex];
return `${item.date}<br/>${item.title}`;
}
},
singleAxis: {
type: 'category',
orient: 'vertical',
data: filtered.map((_, i) => i),
top: 20,
bottom: 20,
left: 120,
width: '80%',
axisLabel: {
interval: 0,
formatter: (value, index) => {
if (!filtered[index]) return '';
return filtered[index].date;
},
align: 'right',
margin: 20,
textStyle: {
color: '#666',
fontSize: 14
}
},
axisLine: {
lineStyle: {
color: '#ccc',
width: 2
}
},
axisPointer: {
animation: true,
label: {
show: true
}
},
splitLine: { show: false }
},
series: [
{
type: 'scatter',
coordinateSystem: 'singleAxis',
data: filtered.map((_, i) => [i, 0]),
symbolSize: 14,
itemStyle: {
color: '#2f79c4',
borderColor: '#fff',
borderWidth: 2
},
label: {
show: true,
formatter: (params) => {
const item = filtered[params.dataIndex];
return item.title;
},
position: 'right',
offset: [20, 0],
color: '#333',
fontSize: 16,
fontWeight: 'bold',
width: 400,
overflow: 'truncate'
}
}
]
};
mainChart.setOption(option);
}, 50);
};
const initTimeline = () => {
if (!mainChartRef.value) return;
mainChart = echarts.init(mainChartRef.value);
updateTimeline(0, Date.now() + 365 * 24 * 3600 * 1000 * 10);
};
const initSlider = () => {
if (!sliderChartRef.value) return;
sliderChart = echarts.init(sliderChartRef.value);
const dates = timelineAllData.value.map(item => parseDate(item.date));
const minDate = Math.min(...dates);
const maxDate = Math.max(...dates);
const rangeMin = minDate - 30 * 24 * 3600 * 1000;
const rangeMax = maxDate + 30 * 24 * 3600 * 1000;
const option = {
grid: {
top: 0,
bottom: 0,
left: 20,
right: 20
},
xAxis: {
type: 'time',
min: rangeMin,
max: rangeMax,
axisLabel: { show: false },
axisTick: { show: false },
axisLine: { show: false },
splitLine: { show: false }
},
yAxis: { show: false },
dataZoom: [
{
type: 'slider',
xAxisIndex: 0,
filterMode: 'weakFilter',
height: 30,
bottom: 10,
handleSize: '100%',
showDetail: true,
start: 0,
end: 100
}
],
series: [
{
type: 'scatter',
data: dates.map(d => [d, 0]),
symbolSize: 5,
itemStyle: { color: '#ccc' }
}
]
};
sliderChart.setOption(option);
sliderChart.on('dataZoom', function () {
const opt = sliderChart.getOption();
const startValue = opt.dataZoom[0].startValue;
const endValue = opt.dataZoom[0].endValue;
let startT, endT;
if (startValue != null && endValue != null) {
startT = startValue;
endT = endValue;
} else {
const range = rangeMax - rangeMin;
const startP = opt.dataZoom[0].start;
const endP = opt.dataZoom[0].end;
startT = rangeMin + range * startP / 100;
endT = rangeMin + range * endP / 100;
}
updateTimeline(startT, endT);
});
};
const initChart = () => {
if (!chartRef.value) return;
myChart = echarts.init(chartRef.value);
const option = {
tooltip: {
trigger: "axis",
backgroundColor: "rgba(255, 255, 255, 0.9)",
borderColor: "#2f79c4",
textStyle: {
color: "#666"
},
formatter: function (params) {
return `<div style="padding: 3px 6px;">
<div style="font-weight: bold; margin-bottom: 4px;">${params[0].name}</div>
<div>数量:<span style="color: #2f79c4; font-weight: bold;">${params[0].value}</span></div>
</div>`;
}
},
grid: {
top: "5%",
left: "1%",
right: "2%",
bottom: "5%",
containLabel: true
},
xAxis: {
type: "category",
boundaryGap: false,
data: [
"2024-12",
"2025-1",
"2025-2",
"2025-3",
"2025-4",
"2025-5",
"2025-6",
"2025-7",
"2025-8",
"2025-9",
"2025-10",
"2025-11"
],
axisLine: {
lineStyle: {
color: "#f0f0f0"
}
},
axisLabel: {
color: "#999",
fontSize: 12
},
axisTick: {
show: false
}
},
yAxis: {
type: "value",
min: 0,
max: 100,
interval: 20,
axisLine: {
show: false
},
axisLabel: {
color: "#999",
fontSize: 12
},
splitLine: {
lineStyle: {
type: "dashed",
color: "#f0f0f0"
}
}
},
series: [
{
data: [45, 52, 62, 62, 62, 65, 52, 75, 75, 75, 82, 92],
type: "line",
symbol: "circle",
symbolSize: 8,
itemStyle: {
color: "#fff",
borderColor: "#2f79c4",
borderWidth: 2
},
lineStyle: {
color: "#2f79c4",
width: 2
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(47, 121, 196, 0.2)"
},
{
offset: 1,
color: "rgba(47, 121, 196, 0)"
}
])
}
}
]
};
myChart.setOption(option);
};
onMounted(() => {
initChart();
initTimeline();
initSlider();
window.addEventListener("resize", () => {
myChart && myChart.resize();
mainChart && mainChart.resize();
sliderChart && sliderChart.resize();
});
});
const next = () => {
if (currentIndex.value < cardList.value.length - 5) {
currentIndex.value++;
}
};
const prev = () => {
if (currentIndex.value > 0) {
currentIndex.value--;
}
};
</script>
<style lang="scss" scoped>
.content-wrapper {
width: 1666px;
height: 2132px;
.main-content {
width: 100%;
position: relative;
margin-bottom: 16px;
.cards-mask {
width: 100%;
overflow: hidden; // 仅在这里隐藏超出部分,不影响外层的按钮
}
.cards-container {
display: flex;
gap: 16px;
transition: transform 0.5s ease; // 平滑过渡动画
width: max-content; // 确保容器宽度由内容撑开
}
.government-card {
width: 307px;
height: 178px;
padding: 16px 26px;
box-sizing: border-box;
border-radius: 10px;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 0 20px rgba(25, 69, 130, 0.1);
cursor: pointer;
.card-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: 358px 358px;
background-repeat: no-repeat;
background-position: center;
filter: blur(20px);
z-index: 0;
opacity: 0.8;
background-color: rgba(5, 33, 77, 0.7); // 调整为更明显的深蓝色
&::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(90deg, rgba(5, 33, 77, 1) 0%, rgba(5, 33, 77, 0) 50%, rgba(5, 33, 77, 1) 100%);
}
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 9px;
position: relative;
z-index: 1;
.card-title {
font-family: "YouSheBiaoTiHei";
font-size: 24px;
font-weight: 400;
line-height: 31px;
color: rgba(255, 255, 255, 1);
text-shadow: 0 0 30px rgba(255, 255, 255, 1);
}
.card-icon {
width: 36px; // 假设大小
height: 36px;
}
}
.card-body {
position: relative;
z-index: 1;
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-start;
.stat-item {
display: flex;
justify-content: space-between;
align-items: center;
height: 30px;
.stat-label,
.stat-value {
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 400;
line-height: 30px;
color: rgba(255, 255, 255, 0.8);
}
}
}
}
.left-btn {
width: 24px;
height: 48px;
position: absolute;
top: 50%;
left: -33px;
transform: translateY(-50%);
cursor: pointer;
z-index: 10;
transition: opacity 0.3s;
&.disabled {
opacity: 0.3;
cursor: not-allowed;
}
}
.right-btn {
width: 24px;
height: 48px;
position: absolute;
top: 50%;
right: -33px;
transform: translateY(-50%);
cursor: pointer;
z-index: 10;
transition: opacity 0.3s;
&.disabled {
opacity: 0.3;
cursor: not-allowed;
}
}
}
.main-charts {
width: 1601px;
height: 500px;
border-radius: 10px;
background-color: rgba(255, 255, 255, 0.65);
box-shadow: 0 0 20px rgba(25, 69, 130, 0.1);
display: flex;
flex-direction: column;
margin-bottom: 22px;
.charts-title {
width: 100%;
height: 48px;
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 17px;
padding-right: 35px;
box-sizing: border-box;
background: linear-gradient(180deg, rgba(231, 243, 255, 1) 0%, rgba(231, 243, 255, 0) 100%);
.title-left {
display: flex;
align-items: center;
img {
width: 18px;
height: 18px;
margin-right: 14px;
}
span {
font-family: YouSheBiaoTiHei;
font-size: 24px;
font-weight: 400;
line-height: 24px;
color: rgb(5, 95, 194);
}
}
.title-right {
display: flex;
height: 48px;
align-items: end;
gap: 12px;
padding-right: 17px;
.custom-select {
width: 160px;
:deep(.el-input) {
height: 32px;
.el-input__wrapper {
background-color: #fff;
box-shadow: 0 0 0 1px #dcdfe6 inset;
border-radius: 4px;
padding: 0 12px;
height: 32px;
&:hover {
box-shadow: 0 0 0 1px #c0c4cc inset;
}
&.is-focus {
box-shadow: 0 0 0 1px #409eff inset;
}
}
.el-input__inner {
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 400;
color: rgb(95, 101, 108);
height: 32px;
line-height: 24px;
&::placeholder {
color: rgb(95, 101, 108);
}
}
}
}
}
}
.charts-content {
flex: 1;
width: 100%;
padding: 20px 40px 20px 40px;
box-sizing: border-box;
.chart-container {
width: 100%;
height: 100%;
}
}
}
.main-text {
width: 1601px;
height: 700px;
display: flex;
justify-content: space-between;
margin-bottom: 16px;
.text-item {
width: 792px;
height: 700px;
border-radius: 10px;
background-color: rgba(255, 255, 255, 0.65);
box-shadow: 0 0 20px rgba(25, 69, 130, 0.1);
.text-item-title {
width: 100%;
height: 48px;
display: flex;
justify-content: flex-start;
align-items: center;
padding-left: 17px;
box-sizing: border-box;
background: linear-gradient(180deg, rgba(231, 243, 255, 1) 0%, rgba(231, 243, 255, 0) 100%);
img {
width: 18px;
height: 18px;
margin-right: 14px;
}
span {
font-family: YouSheBiaoTiHei;
font-size: 24px;
font-weight: 400;
line-height: 24px;
color: rgb(5, 95, 194);
}
}
.text-item-content {
width: 100%;
height: 652px;
padding: 6px 27px 22px 27px;
box-sizing: border-box;
overflow-y: auto;
.dynamic-item {
display: flex;
padding: 16px 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
&:last-child {
border-bottom: none;
}
.item-icon {
width: 24px;
height: 24px;
margin-right: 12px;
margin-top: 3px;
}
.item-right {
flex: 1;
.dynamic-item-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
.item-title {
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 700;
line-height: 30px;
color: rgb(59, 65, 75);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 500px;
}
.item-date {
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 400;
line-height: 30px;
color: rgb(95, 101, 108);
}
}
.dynamic-item-body {
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 400;
line-height: 30px;
color: rgb(95, 101, 108);
margin-top: 0; // 紧贴标题行
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
.dynamic-item-tags {
display: flex;
gap: 8px;
margin-top: 5px;
.tag {
padding: 2px 8px;
border-radius: 4px;
font-family: "Microsoft YaHei";
font-size: 14px;
font-weight: 400;
line-height: 20px;
&.tag-blue {
color: #2f79c4;
background: rgba(47, 121, 196, 0.1);
border: 1px solid rgba(47, 121, 196, 0.3);
}
&.tag-green {
color: #52c41a;
background: rgba(82, 196, 26, 0.1);
border: 1px solid rgba(82, 196, 26, 0.3);
}
&.tag-red {
color: #fa541c;
background: rgba(250, 84, 28, 0.1);
border: 1px solid rgba(250, 84, 28, 0.3);
}
}
}
}
}
}
.text-item-contentOther {
width: 100%;
height: 652px;
padding: 10px 30px 22px 27px;
box-sizing: border-box;
overflow-y: auto;
.ranking-card {
width: 100%;
border-radius: 10px;
border: 1px solid rgb(234, 236, 238);
padding: 12px 24px;
margin-bottom: 12px;
box-sizing: border-box;
&:last-child {
margin-bottom: 0;
}
.ranking-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
.header-left {
display: flex;
align-items: center;
.dept-icons {
display: flex;
margin-right: 12px;
.dept-icon {
width: 24px;
height: 24px;
margin-right: -8px; // 图标叠加效果
&:last-child {
margin-right: 0;
}
}
}
.dept-names {
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 700;
line-height: 24px;
color: rgb(59, 65, 75);
}
}
.header-right {
.joint-count {
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 700;
line-height: 24px;
color: rgb(59, 65, 75);
}
}
}
.ranking-body {
display: flex;
flex-direction: column;
gap: 8px;
.ranking-item {
display: flex;
justify-content: space-between;
align-items: center;
.item-left {
display: flex;
align-items: center;
flex: 1;
overflow: hidden;
.item-type {
padding: 2px 8px;
border-radius: 4px;
font-family: "Microsoft YaHei";
font-size: 14px;
font-weight: 400;
line-height: 20px;
margin-right: 13px;
&.type-bill {
color: #2f79c4;
background: rgba(47, 121, 196, 0.1);
// border: 1px solid rgba(47, 121, 196, 0.3);
}
&.type-order {
color: #2f79c4;
background: rgba(47, 121, 196, 0.1);
// border: 1px solid rgba(47, 121, 196, 0.3);
}
}
.item-title {
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 400;
line-height: 30px;
color: rgb(59, 65, 75);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
}
}
.item-date {
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 400;
line-height: 30px;
color: rgb(95, 101, 108);
margin-left: 16px;
}
}
}
}
}
}
}
.main-bottom {
width: 100%;
height: 700px;
border-radius: 10px;
background-color: rgba(255, 255, 255, 0.65);
box-shadow: 0 0 20px rgba(25, 69, 130, 0.1);
.bottom-item {
width: 100%;
height: 48px;
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 17px;
padding-right: 35px;
box-sizing: border-box;
background: linear-gradient(180deg, rgba(231, 243, 255, 1) 0%, rgba(231, 243, 255, 0) 100%);
.bottom-item-title {
display: flex;
align-items: center;
img {
width: 18px;
height: 18px;
margin-right: 14px;
}
span {
font-family: YouSheBiaoTiHei;
font-size: 24px;
font-weight: 400;
line-height: 24px;
color: rgb(5, 95, 194);
}
}
.bottom-item-select {
display: flex;
height: 48px;
align-items: end;
gap: 8px;
.select-btn {
padding: 4px 16px;
border-radius: 4px;
border: 1px solid rgb(230, 231, 232);
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 400;
line-height: 24px;
color: rgb(95, 101, 108);
cursor: pointer;
background-color: #fff;
// transition: all 0.3s;
&.active {
color: rgb(5, 95, 194);
border-color: rgb(5, 95, 194);
background-color: rgba(231, 243, 255, 1);
}
}
.field-select {
width: 160px;
:deep(.el-input) {
.el-input__wrapper {
height: 32px;
padding: 0 12px;
box-sizing: border-box;
background-color: transparent;
border-radius: 4px;
.el-input__inner {
height: 32px;
line-height: 32px;
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 400;
color: rgb(95, 101, 108);
&::placeholder {
color: rgb(95, 101, 108);
}
}
}
}
}
}
}
.bottom-content {
width: 100%;
height: calc(100% - 48px);
padding: 14px 23px 19px 23px;
box-sizing: border-box;
.timeline-container {
width: 100%;
height: 100%;
border-radius: 4px;
padding: 8px 8px 8px 8px;
background-color: rgb(247, 248, 249);
border: 1px solid rgb(234, 236, 238);
.timeline-item {
width: 100%;
height: 552px;
overflow-y: auto;
&::-webkit-scrollbar {
display: none;
}
}
.timelineBar {
width: 100%;
height: 51px;
background-color: rgba(255, 255, 255, 1);
}
}
}
}
}
</style>
<style lang="scss">
.common-prompt-popper.el-popper {
padding: 8px 16px !important;
border-radius: 10px !important;
background-color: rgb(59, 65, 75) !important;
font-size: 16px !important;
font-weight: 400 !important;
font-family: "Microsoft YaHei" !important;
line-height: 30px !important;
color: #fff !important;
border: none !important;
.el-popper__arrow::before {
background-color: rgb(59, 65, 75) !important;
border-color: rgb(59, 65, 75) !important;
}
}
</style>
<!--科技要闻-->
<template>
<div class="content-wrapper">
全联盟
</div>
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
</script>
<style lang="scss" scoped>
.content-wrapper {
width: 1666px;
height: 2132px;
}
</style>
<!--科技要闻-->
<template>
<div class="content-wrapper">
美对华四全打压
<div class="main-nav">
<div
v-for="item in navList"
:key="item.name"
class="nav-item"
:class="{ active: activeNav === item.name }"
@click="handleNavClick(item.name)"
>
<div class="item-content">
<img v-if="activeNav === item.name" :src="right" class="active-icon" alt="" />
<span>{{ item.name }}</span>
</div>
<img v-if="activeNav === item.name" :src="background" class="active-bg" alt="" />
</div>
</div>
<!-- 切换不同的组件 -->
<AllGovernment v-if="activeNav === '全政府'" />
<AddDomain v-if="activeNav === '全领域'" />
<AllUnion v-if="activeNav === '全联盟'" />
<AllElement v-if="activeNav === '全要素'" />
</div>
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
import right from "./assets/right.png";
import background from "./assets/background.png";
// 组件引入
import AllGovernment from "./components/allGovernment/index.vue";
import AddDomain from "./components/addDomain/index.vue";
import AllUnion from "./components/allUnion/index.vue";
import AllElement from "./components/allElement/index.vue";
const navList = ref([
{ name: "全政府" },
{ name: "全领域" },
{ name: "全联盟" },
{ name: "全要素" }
]);
const activeNav = ref("全政府");
const handleNavClick = (name) => {
activeNav.value = name;
};
</script>
<style lang="scss" scoped>
.content-wrapper {
width: 100%;
width: 1601px;
height: 2203px;
margin: 0 auto;
.main-nav {
width: 100%;
height: 55px;
padding: 4px 5px;
display: flex;
align-items: center;
border-radius: 10px;
background-color: rgba(255, 255, 255, 0.65);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
box-sizing: border-box;
gap: 8px;
margin-bottom: 16px;
.nav-item {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
position: relative;
// transition: all 0.3s;
.item-content {
display: flex;
align-items: center;
z-index: 1;
.active-icon {
width: 18px;
height: 18px;
margin-right: 8px;
}
span {
font-family: 'YouSheBiaoTiHei';
font-size: 24px;
font-weight: 400;
line-height: 31px;
color: rgb(59, 65, 75);
}
}
.active-bg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
height: 60px;
z-index: 0;
}
&.active {
background-color: rgba(246, 250, 255, 1);
border: 1px solid rgba(174, 214, 255, 1);
border-radius: 10px;
span {
color: rgb(5, 95, 194);
}
}
}
}
}
</style>
<template>
<div class="timeline-wrapper">
<button class="arrow left" :disabled="index <= 0" @click="index--">
{{ '<' }}
</button>
<div class="timeline-box">
<div class="line"></div>
<div v-for="(item, i) in showList" :key="item[idKey]" class="node" :style="leftOffset(i)">
<div class="node" :style="leftOffset(i)">
<!-- 圆环 -->
<div class="dot" :class="linePos(i, flip)"></div>
<!-- 卡片:放到线右侧 -->
<div class="card" :class="[cardPos(i, flip), 'right-side']" @click="$emit('click-card', item)">
<div class="time">
{{ item.time }}
</div>
<div class="title">
{{ item.title }}
<img class="item-header-icon" src="@/assets/images/icon/copy.png" style="cursor: pointer;" />
</div>
<div class="content">
{{ item.content }}
</div>
</div>
</div>
</div>
</div>
<button class="arrow right" :disabled="index >= total - 5" @click="index++">
{{ '>' }}
</button>
</div>
</template>
<script>
export default {
name: 'TimeLine',
props: {
data: { // 父组件传入的数组
type: Array,
required: true
},
textKey: { // 要显示的文本字段
type: String,
default: 'text'
},
idKey: { // 唯一标识字段
type: String,
default: 'id'
}
},
data() {
return { index: 0 };
},
computed: {
total() {
return this.data.length;
},
showList() {
return this.data.slice(this.index, this.index + 5);
},
flip() { return this.index % 2 === 1; }
},
methods: {
leftOffset(i) {
return { left: `${(i * 100) / 5}%` };
},
/* 上下层翻转(保留上次逻辑) */
cardPos(i, flip = false) {
return (i % 2) ^ flip ? 'down' : 'up';
},
/* 线延伸方向 = 卡片出现方向 */
linePos(i, flip = false) {
return this.cardPos(i, flip); // up / down
}
}
};
</script>
<style scoped>
/* 样式与之前完全一致,不再重复 */
.timeline-wrapper {
display: flex;
align-items: center;
width: 100%;
position: relative;
padding: 0 40px;
}
.arrow {
position: absolute;
top: 170px;
/* 左右切换按钮 */
width: 24px;
height: 48px;
font-size: 24px;
border-color: #E7F3FF;
border: 0;
background: #E7F3FF;
cursor: pointer;
z-index: 10;
color: #3E84D1;
}
.arrow:disabled {
color: #c0c4cc;
cursor: not-allowed;
}
.left {
left: 0;
border-radius: 0px 4px 4px 0px;
}
.right {
right: 0;
border-radius: 4px 0px 0px 4px;
}
.timeline-box {
flex: 1;
height: 100%;
position: relative;
}
.line {
position: absolute;
left: 0;
right: 0;
top: 50%;
height: 6px;
background-image: url("@/assets/images/bg/timeLine-bg.jpg");
transform: translateY(-50%);
background-size: auto 100%;
}
.node {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
z-index: 2;
}
/* ===== 圆环基础 ===== */
.dot {
width: 14px;
height: 14px;
border-radius: 50%;
border: 3px solid #409eff;
background: #fff;
position: relative;
margin: 0 auto;
z-index: 2;
}
/* ===== 延伸线 ===== */
.dot::after {
content: '';
position: absolute;
left: 50%;
transform: translateX(-1px);
/* 居中细线 */
width: 1px;
background: #409eff;
}
/* 向上节点:线往下伸 */
.dot.up::after {
bottom: 100%;
height: 165px;
/* 圆环底部 → 卡片顶 */
}
/* 向下节点:线往上伸 */
.dot.down::after {
top: 100%;
height: 165px;
}
.card {
position: absolute;
height: 165px;
width: 320px;
padding: 8px 12px;
text-align: left;
cursor: pointer;
font-size: 14px;
}
.time {
color: rgba(5, 95, 194, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px;
text-align: justify;
margin-bottom: 10px;
}
.title {
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px;
text-align: justify;
margin-bottom: 10px;
}
.content {
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;
}
.card.up {
bottom: 20px;
}
.card.down {
top: 20px;
}
</style>
\ No newline at end of file
<!--科技要闻-->
<template>
<div class="content-wrapper">
中美博弈概况
<div class="card-box">
<div class="card-title">
<img class="icon" src="../../assets/icons/title-icon1.png" />
<img class="text" src="../../assets/icons/title-text1.png" />
</div>
</div>
<div class="card-box" style="margin-top: 16px;">
<div class="card-title">
<img class="icon" src="../../assets/icons/title-icon2.png" />
<img class="text" src="../../assets/icons/title-text2.png" />
</div>
<div style="display: flex;height: 530px;">
<Timeline :data="course" text-key="title" id-key="seq" />
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, computed } from "vue";
import Timeline from "./Timeline.vue";
const course = ref([
{
time: "2025年1月",
title: "《AI扩散暂行最终规则》发布",
content: "拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。"
},
{
time: "2025年1月",
title: "特朗普宣布撤销拜登AI规则",
content: "拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。"
},
{
time: "2025年1月",
title: "特朗普签署EO 143202",
content: "特朗普政府宣布撤销拜登AI规则,计划"
},
{
time: "2025年1月",
title: "中国网信办约谈英伟达",
content: "中国网信办约谈英伟达,要求就H20算力芯片漏洞后门安全风险问题进行说明。"
},
{
time: "2025年7月23日",
title: "英伟达H20发放出口许可证",
content: "美国商务部为4月份被实质禁售的英伟达H20发放出口许可证。"
},
{
time: "2025年1月",
title: "《AI扩散暂行最终规则》发布",
content: "拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。"
},
{
time: "2025年1月",
title: "特朗普宣布撤销拜登AI规则",
content: "拜登政府发布《AI扩散暂行最终规则》,建立三级许可制度。"
},
{
time: "2025年1月",
title: "特朗普签署EO 143202",
content: "特朗普政府宣布撤销拜登AI规则,计划"
},
{
time: "2025年1月",
title: "中国网信办约谈英伟达",
content: "中国网信办约谈英伟达,要求就H20算力芯片漏洞后门安全风险问题进行说明。"
},
{
time: "2025年7月23日",
title: "英伟达H20发放出口许可证",
content: "美国商务部为4月份被实质禁售的英伟达H20发放出口许可证。"
}
]);
</script>
<style lang="scss" scoped>
......@@ -15,5 +82,36 @@ import { onMounted, ref, computed } from "vue";
width: 100%;
height: 1416px;
.card-box {
width: 1600px;
height: 700px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: var(---10, 10px);
/* 业务系统/模块阴影 */
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.card-title {
width: 1602px;
height: 48px;
display: flex;
.icon {
/* 合并 */
width: 18.67px;
height: 17.85px;
margin: 14px 16px;
}
.text {
/* Text */
width: 177px;
height: 31px;
margin: 8px 0px;
}
}
}
}
</style>
<template>
<div ref="ballDom" class="ball-box" :style="{ width: '128px', height: '128px' }" />
</template>
<script setup>
/**
* Vue3 水波进度球
* 用法:<WaterBall :percent="67" :size="200" />
*/
import { ref, watch, onMounted } from 'vue'
import * as echarts from 'echarts'
import 'echarts-liquidfill'
/* props */
const props = defineProps({
percent: { type: Number, default: 60 }, // 0~100
size: { type: Number, default: 200 }, // 画布宽高
data: { type: Object, default: {} },
color: { type: Array, default: [] },
})
/* dom */
const ballDom = ref(null)
let instance = null
// const color = ref([0, 0, 0])
// const makeColors = () => {
// props.color[0] = Math.floor(Math.random() * 360) // 随机色相
// props.color[1] = 70 // 固定饱和度
// props.color[2] = 50 // 固定亮度
// }
/* 颜色映射 */
/* 配置项 */
const makeOption = () => {
const p = Math.min(100, Math.max(0, props.percent)) / 100
console.log(props.color, 'colorcolorcolor')
return {
series: [{
type: 'liquidFill',
radius: '90%',
data: [
{ value: p, direction: 'right' },
{ value: p, direction: 'left' } // 两层波浪反向
],
color: [` ${props.color[1]}`, ` ${props.color[0]}`],
waveAnimation: true,
animationEasingUpdate: 'cubicOut',
outline: {
show: true,
borderDistance: 2, // 第一层边框
itemStyle: {
shadowBlur: 0, // 同样设为 0
borderWidth: 1,
borderColor: `${props.color[2]}`,
shadowColor: 'transparent'
}
},
// 1. 关掉波浪的阴影
itemStyle: {
shadowBlur: 0, // 关键:阴影范围设为 0
shadowColor: 'transparent'
},
backgroundStyle: {
color: `${props.color[3]}`,
borderWidth: 1,
borderColor: `${props.color[4]}`, // 中间区域保持透明
shadowBlur: 0
},
label: {
show: true,
formatter: `${props.data.change}` + `${props.data.unit}`,
fontSize: 24,
color: `${props.color[5]}`,
insideColor: `${props.color[5]}`,
}
}]
}
}
/* 初始化 */
const init = () => {
if (instance) instance.dispose()
instance = echarts.init(ballDom.value)
instance.setOption(makeOption())
}
/* 自动更新 */
watch(() => props.percent, () => {
instance?.setOption(makeOption())
})
onMounted(init)
</script>
<style scoped>
.ball-box {
margin: 0 auto;
}
</style>
\ No newline at end of file
<!--科技要闻-->
<!--今日风险-->
<template>
<div class="content-wrapper">
最新风险动态
<div class="policy-monitoring">
<div class="header">
<div class="section" v-for="(section, index) in sectionTab" :key="index" :style="{
width: sections[index].waveBall.length === 2 ? '350px' : '503px',
background: section.background
}">
<img class="section-title" :src="`/public/icon/riskToday/title-` + (index + 1) + `.png`" />
<div class="stats">
<div v-for="value in sections[index].waveBall">
<WaveBall :percent="value.percent" :data="value" :color="section.waterColor" :size="128" />
<div class="waveBall-text">{{ value.title }}</div>
</div>
</div>
<div class="bottm-box" :style="sections[index].waveBall.length === 2 ? 'width: 350px' : 'width:503px'">
<img src="./icon/title-icon-1.png" />
<div class="bottm-box-text" :style="sections[index].waveBall.length === 2 ? 'width: 225px' : 'width:378px'">
{{ sections[index].title }}
</div>
<div style="width: 50px; color: #ffffff">
{{ sections[index].date }}
</div>
</div>
</div>
</div>
<div class="content">
<div class="content-title">
<img class="section-title" src="./icon/title-icon-2.png" />
<div>风险信号</div>
<div class="num">12</div>
</div>
<div style="display: flex">
<div class="risk-signals">
<div class="risk-signals-item" v-for="(item, index) in warningList" :key="index"
@click="handleClickToDetailO(item)">
<div class="item-left" :class="{
itemLeftStatus1: item.signalLevel === '特别重大',
itemLeftStatus2: item.signalLevel === '重大风险'
}">
{{ item.signalLevel ? item.signalLevel : "一般风险" }}
</div>
<div class="item-right">
<div class="text">
{{ item.signalTitle }}
</div>
<div class="time">{{ item.signalTime }}</div>
</div>
</div>
</div>
<div class="news">
<div class="box1-left" @click="handleSwithCurNews('left')">
<div class="icon">
<img src="./icon/box1-left.png" alt="" />
</div>
</div>
<div class="box1-right" @click="handleSwithCurNews('right')">
<div class="icon">
<img src="./icon/box1-right.png" alt="" />
</div>
</div>
<el-carousel ref="carouselRef" style="height: 443px; width: 664px" :autoplay="true" :interval="30000"
arrow="never" indicator-position="none" @change="handleCarouselChange">
<el-carousel-item v-for="(News, NewsIndex) in hotNewsList" :key="NewsIndex">
<div class="carousel-item">
<div class="carousel-title">
<div>
<div class="title-text">
{{ News.title }}
</div>
<div class="title-tag">
{{ News.category }}
</div>
</div>
<img src="./icon/矩形 295.png" style="width: 96px; height: 96px" />
</div>
<div style="/* 矩形 351 */ width: 664px; height: 1px; background: rgba(234, 236, 238, 1)"></div>
<div class="carousel-content">{{ News.content }}</div>
<div style="/* 矩形 351 */ width: 664px; height: 1px; background: rgba(234, 236, 238, 1)"></div>
<!-- <div class="carousel-bottom">
<div class="carousel-bottom-left">{{ News.date + News.source }}</div>
</div> -->
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { color } from "echarts";
import { onMounted, ref, computed } from "vue";
import WaveBall from "./WaveBall.vue";
import { getBillRiskSignal } from "@/api/bill/billHome";
const sectionTab = [
{
textColor: "rgba(9, 88, 217, 1)",
background: "linear-gradient(180.00deg, rgba(9, 88, 217, 1),rgba(9, 88, 217, 0.5) 100%)",
borderColor: "rgba(186, 224, 255, 1)",
waterColor: ["#4E92F4", "#5993EE", "#8EB3ED", "#77A2EB", "#ffffff", "#ffffff"],
title: "政策法规"
},
{
textColor: "rgba(9, 88, 217, 1)",
background: "linear-gradient(180.00deg, rgba(8, 151, 156, 1),rgba(8, 151, 156, 0.5) 100%)",
borderColor: "rgba(186, 224, 255, 1)",
waterColor: ["#4AB9BA", "#5DBFC1", "#86CCCF", "#8DD0D2", "#ffffff", "#ffffff"],
title: "出口管制"
},
{
textColor: "rgba(9, 88, 217, 1)",
background: "linear-gradient(180.00deg, rgba(206, 79, 81, 1),rgba(206, 79, 81, 0.5) 100%)",
borderColor: "rgba(186, 224, 255, 1)",
waterColor: ["#EF797B", "#ED8C8E", "#EAB0B2", "#E7ABAC", "#ffffff", "#ffffff"],
title: "投融资限制"
},
{
textColor: "rgba(9, 88, 217, 1)",
background: "linear-gradient(180.00deg, rgba(212, 107, 8, 1),rgba(212, 107, 8, 0.5) 100%)",
borderColor: "rgba(186, 224, 255, 1)",
waterColor: ["#EFA04F", "#EDA969", "#EABA8C", "#E7AF7A", "#ffffff", "#ffffff"],
title: "市场准入"
}
];
// 模拟从后端获取的数据
const sections = ref([
{
title: "政令:确保美国太空优势",
date: "12-18",
waveBall: [
{
percent: 30, // 估算的百分比
count: 1626,
change: "+3",
unit: "项",
title: "法案(提出)"
},
{
percent: 20, // 估算的百分比
count: 69,
change: "+2",
unit: "个",
title: "政令"
}
]
},
{
title: "对实体清单的更新及修订",
date: "12-18",
waveBall: [
{
percent: 10, // 估算的百分比
count: 128,
change: "+1",
unit: "次",
title: "实体清单"
},
{
percent: 20, // 估算的百分比
count: 69,
change: "+1",
unit: "次",
title: "CCL"
}
]
},
{
title: "SDN清单更新",
waveBall: [
{
percent: 15, // 估算的百分比
count: 35,
change: "+1",
unit: "次",
title: "SDN"
},
{
percent: 5, // 估算的百分比
count: 28,
change: "+1",
unit: "家",
title: "涉军企业"
}
]
},
{
title: "232调查:商用飞机和喷气发动机进口对国家安全的...",
date: "12-18",
waveBall: [
{
percent: 3, // 估算的百分比
count: 215,
change: "+1",
unit: "次",
title: "337调查"
},
{
percent: 3, // 估算的百分比
count: 14,
change: "无新增",
unit: "次",
title: "230调查"
},
{
percent: 3, // 估算的百分比
count: 9,
change: "无新增",
unit: "次",
title: "301调查"
}
]
}
]);
// 风险信号
const warningList = ref([]);
// 获取法案风险信号
const handlegetBillRiskSignal = async () => {
const params = {
moduleId: "0100"
};
try {
const res = await getBillRiskSignal(params);
console.log("法案风险信号", res);
if (res.code === 200) {
warningList.value = res.data;
}
} catch (error) { }
};
const hotNewsList = ref([
{
title: "美国白宫发布关于进一步延长TikTok执法宽限期的行政令",
category: "政策及立法打压风险",
content:
"2025年1月20日第14166号行政命令第2(a)条(《保护美国免受外国对抗者控制应用法案》对TikTok的适用)规定的执行延迟,并由2025年4月4日第14258号行政命令(延长TikTok执法延迟)和2025年6月19日第14310号行政命令(进一步延长TikTok执法延迟)所延长,进一步延长至2025年12月16日。在此期间,司法部不得采取任何行动执行《保护美国人免受外国对抗者控制应用法案》(以下简称“法案”)(公共法118-50,H部),也不得对任何违反该法案的实体处以任何处罚,包括分发、维护、更新(或促成分发,维护或更新任何外国对手控制的应用,如本法所定义。鉴于本指示,即使在上述规定期限届满后,司法部也应继续与相关部门合作,以确保美国国家安全和公民隐私权利不受威胁。",
date: "2025年9月16日",
source: "美国白宫·总统行政令"
},
{
title: "美国白宫发布关于进一步延长TikTok执法宽限期的行政令",
category: "政策及立法打压风险",
content:
"2025年1月20日第14166号行政命令第2(a)条(《保护美国免受外国对抗者控制应用法案》对TikTok的适用)规定的执行延迟,并由2025年4月4日第14258号行政命令(延长TikTok执法延迟)和2025年6月19日第14310号行政命令(进一步延长TikTok执法延迟)所延长,进一步延长至2025年12月16日。在此期间,司法部不得采取任何行动执行《保护美国人免受外国对抗者控制应用法案》(以下简称“法案”)(公共法118-50,H部),也不得对任何违反该法案的实体处以任何处罚,包括分发、维护、更新(或促成分发,维护或更新任何外国对手控制的应用,如本法所定义。鉴于本指示,即使在上述规定期限届满后,司法部也应继续与相关部门合作,以确保美国国家安全和公民隐私权利不受威胁。",
date: "2025年9月16日",
source: "美国白宫·总统行政令"
}
]);
const curNews = ref({});
const carouselRef = ref(null);
const curHotNewsListIndex = ref(0);
const handleCarouselChange = index => {
curHotNewsListIndex.value = index;
if (hotNewsList.value && hotNewsList.value.length > 0) {
curNews.value = hotNewsList.value[index];
}
};
const handleSwithCurNews = name => {
if (name === "left") {
carouselRef.value.prev();
} else {
carouselRef.value.next();
}
};
onMounted(() => {
// 这里可以添加从后端获取数据的代码
handlegetBillRiskSignal();
console.log("页面加载完成,可以获取数据了");
});
</script>
<style lang="scss" scoped>
.content-wrapper {
width: 100%;
height: 904px;
// height: 100%;
.policy-monitoring {
font-family: Arial, sans-serif;
}
.header {
display: flex;
justify-content: space-around;
margin-bottom: 20px;
}
.content {
/* 容器 83 */
/* 容器 83 */
width: 1601px;
height: 568px;
box-sizing: border-box;
border: 1px solid rgba(255, 255, 255, 1);
border-radius: var(---10, 10px);
/* 业务系统/模块阴影 */
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 0.65);
.content-title {
/* 块级标题 */
width: 1602px;
height: 48px;
box-sizing: border-box;
border-bottom: 1px solid rgba(255, 255, 255, 1);
background: linear-gradient(180deg, rgba(255, 241, 240, 0.5), rgba(255, 241, 240, 0) 100%);
color: rgba(206, 79, 81, 1);
font-family: YouSheBiaoTiHei;
font-style: Regular;
font-size: 24px;
font-weight: 400;
line-height: 31px;
letter-spacing: 0px;
text-align: left;
display: flex;
img {
/* 矢量 347 */
width: 22px;
height: 18px;
}
.num {
/* 数据展示/Badge徽标数/亮色/数字 */
height: 22px;
/* 自动布局 */
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
gap: 10;
padding: 0px 8px 0px 8px;
border-radius: 100px;
background: rgba(206, 79, 81, 1);
color: rgba(255, 255, 255, 1);
margin: 12px;
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: center;
}
}
}
.section {
/* 容器 535 */
width: 350px;
height: 320px;
box-sizing: border-box;
border: 1px solid rgba(255, 255, 255, 1);
border-radius: var(---10, 10px);
/* 业务系统/模块阴影 */
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 0.65);
}
.section-title {
margin: 8px 16px;
/* 容器 1559 */
width: 125px;
height: 31px;
}
.stats {
/* 容器 519 */
height: 210px;
display: flex;
justify-content: left;
margin-top: 10px;
padding: 0 39px;
.waveBall-text {
margin-top: 17px;
color: #ffffff;
font-family: Microsoft YaHei;
font-style: Bold;
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px;
text-align: center;
}
}
.bottm-box {
/* 容器 1561 */
display: flex;
width: 350px;
height: 48px;
/* 自动布局 */
flex-direction: row;
justify-content: flex-start;
align-items: center;
// gap: 15;
color: #ffffff;
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
.bottm-box-text {
white-space: nowrap;
/* 保持在一行 */
overflow: hidden;
/* 隐藏超出部分 */
text-overflow: ellipsis;
/* 超出部分显示省略号 */
}
img {
/* 矢量 1667 */
width: 12px;
height: 16px;
margin: 16px 20px;
}
}
.risk-signals {
width: 769px;
overflow-y: auto;
overflow-x: hidden;
box-sizing: border-box;
padding-right: 20px;
.risk-signals-item {
margin-left: 23px;
height: 47px;
width: 780px;
display: flex;
cursor: pointer;
&:hover {
background: var(--color-bg-hover);
}
.itemLeftStatus1 {
color: rgba(245, 34, 45, 1) !important;
background: rgba(255, 241, 240) !important;
}
.itemLeftStatus2 {
color: rgba(250, 140, 22, 1) !important;
background: rgba(255, 247, 230, 1) !important;
}
.item-left {
margin-top: 4px;
margin-left: 2px;
width: 40px;
height: 40px;
border-radius: 20px;
color: rgba(82, 196, 26, 1);
background: rgba(246, 255, 237, 1);
font-family: Microsoft YaHei;
font-size: 12px;
font-weight: 400;
line-height: 14px;
box-sizing: border-box;
padding: 6px 4px;
text-align: center;
}
.item-right {
margin-left: 13px;
width: 722px;
height: 47px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
display: flex;
.text {
width: 598px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 47px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.time {
width: 88px;
margin-left: 5px;
line-height: 47px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
.news {
/* 容器 1567 */
width: 760px;
height: 491px;
margin-left: 37px;
/* 自动布局 */
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
gap: 16;
padding: 24px 48px 24px 48px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
background: rgba(255, 255, 255, 0.65);
position: relative;
.box1-left {
position: absolute;
left: 0;
top: 200px;
width: 24px;
height: 48px;
background: #e7f1ff;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
z-index: 10;
.icon {
width: 11px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
}
.box1-right {
position: absolute;
right: 0;
top: 200px;
width: 24px;
height: 48px;
background: #e7f1ff;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
z-index: 10;
.icon {
width: 11px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
}
.carousel-item {
height: 480px;
width: 736px;
.carousel-title {
width: 664px;
height: 96px;
margin: 14px 0;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-style: Bold;
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px;
text-align: justify;
display: flex;
.title-text {
/* 美国白宫发布关于进一步延长TikTok执法宽限期的行政令 */
width: 547px;
height: 26px;
}
.title-tag {
/* 容器 1563 */
width: 190px;
height: 30px;
margin-top: 12px;
/* 自动布局 */
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
gap: 10;
padding: 0px 12px 0px 12px;
border-radius: 20px;
background: rgba(206, 79, 81, 0.1);
color: rgba(206, 79, 81, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
}
}
.carousel-content {
width: 664px;
margin-top: 16px;
height: 296px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
}
.carousel-bottom {
/* 容器 1566 */
width: 664px;
height: 34px;
}
}
}
h3 {
margin-bottom: 10px;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
}
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论