提交 179a6cc5 authored 作者: huhuiqing's avatar huhuiqing

最新风险动态,博弈概况

上级 16823566
<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>
.content-wrapper {
width: 100%;
height: 1416px;
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
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论