Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
1
合并请求
1
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
4adeeffb
提交
4adeeffb
authored
3月 06, 2026
作者:
yanpeng
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
领域意见修改
上级
ab0482ce
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
2305 行增加
和
267 行删除
+2305
-267
right-white.png
...ZMOverView/components/fourSuppress/assets/right-white.png
+0
-0
index-back.vue
...mponents/fourSuppress/components/addDomain/index-back.vue
+2092
-0
index.vue
...ew/components/fourSuppress/components/addDomain/index.vue
+199
-54
mockdata.json
...omponents/fourSuppress/components/addDomain/mockdata.json
+0
-204
index.vue
src/views/ZMOverView/components/fourSuppress/index.vue
+4
-3
index.vue
src/views/ZMOverView/index.vue
+10
-6
没有找到文件。
src/views/ZMOverView/components/fourSuppress/assets/right-white.png
0 → 100644
浏览文件 @
4adeeffb
494 Bytes
src/views/ZMOverView/components/fourSuppress/components/addDomain/index-back.vue
0 → 100644
浏览文件 @
4adeeffb
<!--全领域-->
<
template
>
<div
class=
"content-wrapper"
>
<div
class=
"btn-wrapper"
@
mouseenter=
"stopAutoPlay"
@
mouseleave=
"startAutoPlay(true)"
>
<div
class=
"cards-mask"
>
<div
class=
"btn-box"
:style=
"
{ transform: `translateX(-${currentIndex * (cardWidth + cardGap)}px)` }">
<div
class=
"btn-item-outer"
v-for=
"(item, indexx) in buttonsData"
:key=
"indexx"
>
<div
v-for=
"(value, index) in item"
:key=
"index"
class=
"btn-item"
:style=
"
{ background: value.background }"
>
<div
:style=
"
{
backgroundImage: 'url(' + `/public/icon/ZM/btn-icon2-${value.originalIndex}.png` + ')'
}"
class="btn-left-text"
>
{{
value
.
text
}}
</div>
<div
class=
"btn-right"
>
{{
value
.
count
+
"次"
}}
</div>
</div>
</div>
</div>
</div>
<img
:src=
"leftBtn"
alt=
""
@
click=
"prev"
class=
"left-btn"
/>
<img
:src=
"rightBtn"
alt=
""
@
click=
"next"
class=
"right-btn"
/>
</div>
<div
class=
"main-charts"
>
<div
class=
"charts-title"
>
<div
class=
"title-left"
>
<img
src=
"./icon/icon-1.png"
alt=
""
/>
<span>
美对华领域打压遏制数量趋势
</span>
</div>
<div
class=
"title-right"
>
<el-select
v-model=
"deptValue"
placeholder=
"全部部门"
class=
"custom-select"
@
change=
"handleGetDomainContainmentTrend"
>
<el-option
label=
"全部部门"
value=
""
/>
<el-option
v-for=
"item in departmentList"
:key=
"item.departId"
:label=
"item.departName"
:value=
"item.departId"
/>
</el-select>
<el-select
v-model=
"methodValue"
placeholder=
"全部制裁手段"
class=
"custom-select"
@
change=
"handleGetDomainContainmentTrend"
>
<el-option
v-for=
"item in methodOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</div>
</div>
<div
class=
"charts-content"
>
<div
id=
"chartRef"
class=
"chart-container"
></div>
</div>
</div>
<div
class=
"bottom-content"
>
<div
class=
"news-section main-charts"
>
<div
class=
"charts-title news-title"
>
<div
class=
"title-left"
>
<img
src=
"./icon/icon-2.png"
alt=
""
style=
"width: 22px; height: 18px"
/>
<span>
美对华领域打压遏制最新动态
</span>
</div>
<div
class=
"title-right-select"
>
<el-select
v-model=
"selectedFieldForLatest"
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=
"news-content"
>
<div
v-for=
"(value, idx) in newsList"
:key=
"idx"
class=
"news-item"
>
<div
class=
"news-item-title"
>
<div
class=
"tag-container"
>
<!--
<div
v-for=
"tag in value.tags"
:key=
"tag"
:class=
"getTagClass(tag)"
>
{{
tag
}}
</div>
-->
<AreaTag
v-for=
"(tag, index) in value.tags"
:key=
"index"
:tagName=
"tag"
></AreaTag>
</div>
<div
class=
"date"
>
{{
value
.
date
+
" · "
+
value
.
type
}}
</div>
</div>
<div
class=
"content-title"
@
click=
"handleClickTitle(value)"
>
{{
value
.
title
}}
</div>
<el-tooltip
effect=
"dark"
:content=
"value.content"
popper-class=
"common-prompt-popper"
placement=
"top"
:show-after=
"500"
>
<div
class=
"content-text"
>
{{
value
.
content
}}
</div>
</el-tooltip>
</div>
</div>
</div>
<div
class=
"empty-section"
>
<div
class=
"bottom-item"
>
<div
class=
"bottom-item-title"
>
<img
:src=
"icon3"
alt=
""
/>
<span>
美对华领域打压遏制排行
</span>
</div>
</div>
<div
class=
"select-box"
>
<div
class=
"rank-btns"
>
<div
class=
"rank-btn"
:class=
"
{ active: rankType === 'institution' }" @click="rankType = 'institution'">
对我打压机构
</div>
<div
class=
"rank-btn"
:class=
"
{ active: rankType === 'enterprise' }" @click="rankType = 'enterprise'">
受打压企业
</div>
<div
class=
"rank-btn"
:class=
"
{ active: rankType === 'school' }" @click="rankType = 'school'">
受打压院校
</div>
</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
class=
"main-box"
v-loading=
"rankLoading"
element-loading-background=
"rgba(255, 255, 255, 0.5)"
>
<!-- 机构排行的原有样式 -->
<template
v-if=
"rankType === 'institution'"
>
<div
v-for=
"(item, index) in rankList"
:key=
"index"
class=
"rank-item"
>
<div
class=
"rank-num"
:class=
"'rank-' + (index + 1)"
>
{{
index
+
1
}}
</div>
<img
:src=
"item.orgPicture ? item.orgPicture : defaultImg"
alt=
""
class=
"rank-icon"
/>
<div
class=
"rank-name"
:title=
"item.name"
>
{{
item
.
name
}}
</div>
<div
class=
"rank-progress-container"
>
<div
class=
"rank-progress-bar"
:style=
"
{ width: getProgressWidth(item.count) }">
</div>
</div>
<div
class=
"rank-count"
>
{{
item
.
count
}}
次
</div>
</div>
</
template
>
<!-- 企业/院校排行的表格样式 -->
<
template
v-else
>
<div
class=
"table-header"
>
<div
class=
"col-rank"
></div>
<div
class=
"col-name"
style=
"color: rgb(59, 65, 75); font-weight: 700"
>
{{
rankType
===
"enterprise"
?
"公司名称"
:
"院校名称"
}}
</div>
<div
class=
"col-domain"
style=
"color: rgb(59, 65, 75); font-weight: 700"
>
所属领域
</div>
<div
class=
"col-date"
style=
"color: rgb(59, 65, 75); font-weight: 700"
>
制裁时间
</div>
<div
class=
"col-member"
v-if=
"rankType !== 'school'"
style=
"color: rgb(59, 65, 75); font-weight: 700"
>
关键人物
</div>
</div>
<div
class=
"table-list"
>
<div
v-for=
"(item, index) in rankList"
:key=
"index"
class=
"table-row"
>
<div
class=
"col-rank rank-num"
:class=
"'rank-' + (index + 1)"
>
{{
index
+
1
}}
</div>
<div
class=
"col-name flex-align"
>
<img
:src=
"item.orgPicture ? item.orgPicture : defaultImg"
class=
"rank-icon"
/>
<span
class=
"text-ellipsis"
:title=
"item.name"
>
{{
item
.
name
}}
</span>
</div>
<div
class=
"col-domain"
>
<div
class=
"domain-tags"
>
<span
v-for=
"(tag, tIndex) in item.domains.slice(0, rankType === 'enterprise' ? 2 : 3)"
:key=
"tIndex"
class=
"mini-tag"
:class=
"getTagClass(tag)"
>
{{
tag
}}
</span>
</div>
</div>
<div
class=
"col-date"
>
{{
item
.
date
}}
</div>
<div
class=
"col-member"
v-if=
"rankType !== 'school'"
>
{{
item
.
member
}}
</div>
</div>
</div>
</
template
>
</div>
</div>
</div>
<div
class=
"line-time"
>
<div
class=
"bottom-item"
>
<div
class=
"bottom-item-title"
>
<img
:src=
"icon4"
alt=
""
/>
<span>
美对我领域打压遏制时间线
</span>
</div>
<el-select
v-model=
"selectedFieldTimeline"
placeholder=
"全部领域"
class=
"field-select"
@
change=
"handleGetDomainContainmentTimeline"
>
<el-option
v-for=
"item in fieldOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</div>
<div
class=
"line-main"
>
<div
class=
"svg-container"
>
<svg
:viewBox=
"`0 0 ${svgWidth} ${svgHeight}`"
width=
"100%"
>
<defs>
<marker
id=
"arrow"
markerWidth=
"10"
markerHeight=
"10"
refX=
"8"
refY=
"3"
orient=
"auto"
markerUnits=
"strokeWidth"
>
<path
d=
"M0,0 L0,6 L9,3 z"
fill=
"#e8f2ff"
/>
</marker>
</defs>
<path
:d=
"snakePath"
fill=
"none"
stroke=
"rgba(185, 220, 255, 1)"
stroke-width=
"5"
/>
<g
v-for=
"(label, index) in axisDates"
:key=
"'date-' + index"
>
<foreignObject
:x=
"label.x"
:y=
"label.y"
width=
"80"
height=
"60"
style=
"overflow: visible"
>
<div
class=
"axis-date-label"
>
<div
class=
"year"
>
{{ label.year }}
</div>
<div
class=
"month"
>
{{ label.month }}
</div>
</div>
</foreignObject>
</g>
<g
v-for=
"(node, index) in timelineNodes"
:key=
"index"
@
click=
"handleTimeLineNode(node)"
>
<line
:x1=
"node.x"
:y1=
"node.y"
:x2=
"node.x"
:y2=
"node.y + 150"
stroke=
"#1677ff"
stroke-width=
"1"
/>
<circle
:cx=
"node.x"
:cy=
"node.y"
r=
"4"
fill=
"#fff"
stroke=
"#1677ff"
stroke-width=
"3"
/>
<foreignObject
:x=
"node.contentX"
:y=
"node.contentY"
:width=
"node.contentWidth"
:height=
"node.contentHeight"
style=
"overflow: visible"
>
<div
class=
"timeline-content-item"
>
<div
class=
"item-tags"
>
<!-- <span v-for="tag in node.tags" :key="tag" :class="getTagClass(tag)">{{ tag }}</span> -->
<AreaTag
v-for=
"(tag, idx) in node.tags"
:key=
"idx"
:tagName=
"tag"
></AreaTag>
</div>
<div
class=
"item-title"
>
<CommonPrompt
:content=
"node.title"
/>
</div>
<el-tooltip
effect=
"dark"
:content=
"node.content"
popper-class=
"common-prompt-popper"
placement=
"top"
:show-after=
"500"
>
<div
class=
"item-desc"
>
{{ node.content }}
</div>
</el-tooltip>
<div
class=
"item-footer"
>
{{ node.info }}
</div>
</div>
</foreignObject>
</g>
</svg>
</div>
</div>
<div
class=
"left-btn"
@
click=
"handleLeft"
>
<img
src=
"@/assets/icons/card-btn-left.png"
alt=
""
/>
</div>
<div
class=
"right-btn"
@
click=
"handleRight"
>
<img
src=
"@/assets/icons/card-btn-right.png"
alt=
""
/>
</div>
</div>
</div>
</template>
<
script
setup
>
import
{
ref
,
computed
,
onMounted
,
watch
,
inject
,
onUnmounted
}
from
"vue"
;
import
{
useRouter
}
from
"vue-router"
;
import
setChart
from
"@/utils/setChart"
;
import
getMultiLineChart
from
"./multiLineChart"
;
import
CommonPrompt
from
"../../../../commonPrompt/index.vue"
;
import
leftBtn
from
"../../assets/left-btn.png"
;
import
rightBtn
from
"../../assets/right-btn.png"
;
import
icon3
from
"./icon/icon-3.png"
;
import
icon4
from
"./icon/icon-4.png"
;
import
defaultImg
from
"../../../../assets/images/default-icon2.png"
;
import
{
getAllDomainCount
,
getDomainContainmentTrend
,
getTechnologyGameAnalysis
,
getDomainContainmentRanking
,
getDomainContainmentTimeline
}
from
"@/api/zmOverview/allDomains"
;
import
{
getUSGovernmentLatestDynamic
,
getDepartmentList
,
getSanTypeList
}
from
"@/api/allGovernment.js"
;
import
{
ElMessage
}
from
"element-plus"
;
const
router
=
useRouter
();
const
activeDate
=
inject
(
"activeDate"
);
const
deptValue
=
ref
(
""
);
const
methodValue
=
ref
(
""
);
const
departmentList
=
ref
([]);
const
methodOptions
=
ref
([
// { label: "全部制裁手段", value: "" },
// { label: "法案", value: "-1" },
// { label: "政令", value: "-2" },
// { label: "实体清单", value: "1" },
// { label: "特别国民指定清单", value: "2" },
// { label: "涉军企业", value: "3" },
// { label: "行业制裁识别清单", value: "4" },
// { label: "无法核实清单", value: "5" },
// { label: "军事最终用户清单", value: "6" },
// { label: "非SDN中国军工企业名单", value: "7" },
// { label: "拒绝往来人员清单", value: "8" },
// { label: "军事最终用途与最终用户规则", value: "9" },
// { label: "欧盟合并制裁清单", value: "10" },
// { label: "英国制裁清单", value: "11" },
// { label: "加拿大合并自主制裁清单", value: "12" },
// { label: "商业管制清单", value: "13" }
]);
const
handleGetSanList
=
async
()
=>
{
const
params
=
{
orgId
:
deptValue
.
value
};
try
{
const
res
=
await
getSanTypeList
(
params
);
console
.
log
(
"制裁手段列表"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
methodOptions
.
value
=
res
.
data
.
map
(
item
=>
{
return
{
label
:
item
.
name
,
value
:
item
.
id
};
});
}
}
catch
(
error
)
{}
};
const
getDepartmentListData
=
async
()
=>
{
const
params
=
{
sanTypeId
:
methodValue
.
value
};
try
{
const
res
=
await
getDepartmentList
(
params
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
departmentList
.
value
=
res
.
data
;
}
}
catch
(
error
)
{
console
.
error
(
"获取部门数据失败:"
,
error
);
}
};
watch
(
()
=>
methodValue
.
value
,
val
=>
{
getDepartmentListData
();
}
);
watch
(
()
=>
deptValue
.
value
,
val
=>
{
handleGetSanList
();
}
);
const
rankType
=
ref
(
"institution"
);
const
rankLoading
=
ref
(
false
);
const
selectedField
=
ref
(
""
);
const
selectedFieldForLatest
=
ref
(
""
);
const
selectedFieldTimeline
=
ref
(
""
);
const
timelineContainerWidth
=
1700
;
// 美政府部门打压遏制最新动态
const
newsList
=
ref
([]);
const
getUSGovernmentLatestDynamicData
=
async
()
=>
{
try
{
const
res
=
await
getUSGovernmentLatestDynamic
();
if
(
res
.
code
===
200
&&
res
.
data
)
{
// 将接口数据转换为 newsList 需要的格式
newsList
.
value
=
res
.
data
.
map
(
item
=>
{
const
dateObj
=
new
Date
(
item
.
time
);
const
formattedDate
=
`
${
dateObj
.
getFullYear
()}
年
${
dateObj
.
getMonth
()
+
1
}
月
${
dateObj
.
getDate
()}
日`
;
return
{
id
:
item
.
id
,
tags
:
item
.
industrylist
||
[],
date
:
formattedDate
,
type
:
item
.
orgName
||
"未知机构"
,
// 使用 orgName 作为类型信息
title
:
item
.
title
,
content
:
item
.
content
||
item
.
title
// 如果 content 为空,使用 title 填充
};
});
}
}
catch
(
error
)
{
console
.
error
(
"获取美政府部门打压遏制最新动态失败:"
,
error
);
}
};
const
handleClickTitle
=
item
=>
{
if
(
!
item
||
!
item
.
id
)
return
;
// 打开新标签页
const
{
href
}
=
router
.
resolve
({
path
:
"/newsAnalysis"
,
query
:
{
newsId
:
item
.
id
}
});
window
.
open
(
href
,
"_blank"
);
};
const
timelineList
=
ref
([]);
// 处理时间线数据的方法
const
processTimelineData
=
rawData
=>
{
if
(
!
rawData
||
!
Array
.
isArray
(
rawData
)
||
rawData
.
length
===
0
)
{
return
[];
}
return
rawData
.
map
(
item
=>
{
const
eventDate
=
item
.
eventDate
?
new
Date
(
item
.
eventDate
)
:
null
;
const
formattedDate
=
eventDate
?
`
${
eventDate
.
getFullYear
()}
年
${
eventDate
.
getMonth
()
+
1
}
月`
:
""
;
let
tags
=
[];
if
(
item
.
eventDomainList
&&
Array
.
isArray
(
item
.
eventDomainList
))
{
if
(
!
selectedFieldTimeline
.
value
)
{
tags
=
item
.
eventDomainList
.
slice
(
0
,
3
).
map
(
domain
=>
domain
.
domainName
||
""
);
}
else
{
const
matchedIndex
=
item
.
eventDomainList
.
findIndex
(
domain
=>
domain
.
domainId
===
selectedFieldTimeline
.
value
);
if
(
matchedIndex
!==
-
1
)
{
const
matchedItem
=
item
.
eventDomainList
[
matchedIndex
];
const
remainingItems
=
item
.
eventDomainList
.
filter
((
_
,
idx
)
=>
idx
!==
matchedIndex
);
const
sortedList
=
[
matchedItem
,
...
remainingItems
];
tags
=
sortedList
.
slice
(
0
,
3
).
map
(
domain
=>
domain
.
domainName
||
""
);
}
else
{
tags
=
item
.
eventDomainList
.
slice
(
0
,
3
).
map
(
domain
=>
domain
.
domainName
||
""
);
}
}
}
return
{
date
:
formattedDate
,
tags
:
tags
,
title
:
item
.
eventName
||
""
,
content
:
item
.
eventDesc
||
""
,
info
:
`
${
item
.
eventDate
||
""
}
·
${
item
.
eventType
||
""
}
`
,
eventId
:
item
.
eventId
,
eventOrg
:
item
.
eventOrg
,
eventType
:
item
.
eventType
,
eventCountryImg
:
item
.
eventCountryImg
,
eventDomainList
:
item
.
eventDomainList
};
});
};
// 获取领域遏制时间线数据
const
handleGetDomainContainmentTimeline
=
async
()
=>
{
try
{
const
params
=
{};
if
(
selectedFieldTimeline
.
value
)
{
params
.
domain
=
selectedFieldTimeline
.
value
;
}
console
.
log
(
"美对我领域打压遏制时间线"
,
params
);
const
res
=
await
getDomainContainmentTimeline
(
params
);
console
.
log
(
"美对我领域打压遏制时间线"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
// 处理返回的数据结构
const
processedData
=
processTimelineData
(
res
.
data
);
// processedData.forEach(item => {
// if (item.eventDomainList && Array.isArray(item.eventDomainList)) {
// if (!selectedFieldTimeline.value) {
// item.eventDomainList = item.eventDomainList.slice(0, 3);
// } else {
// const matchedIndex = item.eventDomainList.findIndex(
// domain => domain.domainId === selectedFieldTimeline.value
// );
// if (matchedIndex !== -1) {
// const matchedItem = item.eventDomainList[matchedIndex];
// const remainingItems = item.eventDomainList.filter((_, idx) => idx !== matchedIndex);
// item.eventDomainList = [matchedItem, ...remainingItems.slice(0, 2)];
// } else {
// item.eventDomainList = item.eventDomainList.slice(0, 3);
// }
// }
// }
// });
timelineList
.
value
=
processedData
;
console
.
log
(
"timelineList"
,
timelineList
.
value
);
}
}
catch
(
error
)
{
console
.
error
(
"获取美对我领域打压遏制时间线失败:"
,
error
);
// 设置默认空数组
timelineList
.
value
=
[];
}
};
const
maxPerRow
=
3
;
const
nodeGapX
=
420
;
const
rowHeight
=
230
;
const
startX
=
250
;
const
startY
=
45
;
const
timeLineActiveIndex
=
ref
(
0
);
const
axisDates
=
computed
(()
=>
{
const
dates
=
[];
if
(
timelineList
.
value
.
length
>
0
)
{
dates
.
push
({
year
:
timelineList
.
value
[
0
].
date
.
split
(
" "
)[
0
],
month
:
timelineList
.
value
[
0
].
date
.
split
(
" "
)[
1
],
x
:
startX
-
140
,
y
:
startY
-
25
});
const
lastNode
=
timelineNodes
.
value
[
timelineNodes
.
value
.
length
-
1
];
const
isEvenRow
=
lastNode
.
row
%
2
===
0
;
const
endX
=
isEvenRow
?
lastNode
.
x
+
400
:
lastNode
.
x
-
140
;
dates
.
push
({
year
:
timelineList
.
value
[
timelineList
.
value
.
length
-
1
].
date
.
split
(
" "
)[
0
],
month
:
timelineList
.
value
[
timelineList
.
value
.
length
-
1
].
date
.
split
(
" "
)[
1
],
x
:
endX
,
y
:
lastNode
.
y
-
25
});
}
return
dates
;
});
const
handleLeft
=
()
=>
{
if
(
timeLineActiveIndex
.
value
===
0
)
{
ElMessage
.
warning
(
"当前已经是第一组数据!"
);
}
else
{
timeLineActiveIndex
.
value
--
;
}
};
const
handleRight
=
()
=>
{
if
(
timeLineActiveIndex
.
value
===
timelineList
.
value
.
length
%
9
)
{
ElMessage
.
warning
(
"当前已经是最后一组数据!"
);
}
else
{
timeLineActiveIndex
.
value
++
;
}
console
.
log
(
"axisDates"
,
axisDates
.
value
);
console
.
log
(
"timelineNodes"
,
timelineNodes
.
value
);
};
const
timelineNodes
=
computed
(()
=>
{
// 计算起始索引:activeIndex * 9
const
startIndex
=
timeLineActiveIndex
.
value
*
9
;
// 计算结束索引:起始索引 + 9(因为slice的第二个参数是结束索引,不包含)
const
endIndex
=
timeLineActiveIndex
.
value
+
9
;
const
showTimeLineList
=
timelineList
.
value
.
slice
(
startIndex
,
endIndex
);
console
.
log
(
"时间线相关数据 showTimeLineList =>"
,
showTimeLineList
);
console
.
log
(
"时间线相关数据 timelineList =>"
,
timelineList
.
value
);
return
showTimeLineList
.
map
((
item
,
index
)
=>
{
const
row
=
Math
.
floor
(
index
/
maxPerRow
);
const
col
=
index
%
maxPerRow
;
let
x
;
if
(
row
%
2
===
0
)
{
x
=
startX
+
col
*
nodeGapX
;
}
else
{
x
=
startX
+
(
maxPerRow
-
1
-
col
)
*
nodeGapX
;
}
const
y
=
startY
+
row
*
rowHeight
;
const
contentX
=
x
+
20
;
const
contentY
=
y
+
10
;
return
{
...
item
,
x
,
y
,
row
,
col
,
contentX
,
contentY
,
contentWidth
:
320
,
contentHeight
:
180
};
});
});
const
getColorName
=
tag
=>
{
const
tagColorMap
=
{
航空航天
:
"blue"
,
生物科技
:
"blue"
,
集成电路
:
"blue"
,
能源
:
"green"
,
新材料
:
"green"
,
人工智能
:
"red"
};
if
(
tagColorMap
[
tag
])
return
tagColorMap
[
tag
];
const
colors
=
[
"blue"
,
"green"
,
"red"
,
"orange"
,
"purple"
,
"cyan"
];
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
getTagClass
=
tag
=>
{
return
"tag-item "
+
`tag-
${
getColorName
(
tag
)}
`
;
};
const
snakePath
=
computed
(()
=>
{
if
(
timelineNodes
.
value
.
length
===
0
)
return
""
;
let
path
=
`M
${
startX
-
100
}
${
startY
}
`
;
path
+=
` L
${
timelineNodes
.
value
[
0
].
x
}
${
timelineNodes
.
value
[
0
].
y
}
`
;
for
(
let
i
=
0
;
i
<
timelineNodes
.
value
.
length
-
1
;
i
++
)
{
const
curr
=
timelineNodes
.
value
[
i
];
const
next
=
timelineNodes
.
value
[
i
+
1
];
if
(
curr
.
row
!==
next
.
row
)
{
const
radius
=
rowHeight
/
2
;
if
(
curr
.
row
%
2
===
0
)
{
const
turnX
=
curr
.
x
+
400
;
path
+=
` L
${
turnX
}
${
curr
.
y
}
`
;
path
+=
` A
${
radius
}
${
radius
}
0 0 1
${
turnX
}
${
next
.
y
}
`
;
path
+=
` L
${
next
.
x
}
${
next
.
y
}
`
;
}
else
{
const
turnX
=
curr
.
x
-
100
;
path
+=
` L
${
turnX
}
${
curr
.
y
}
`
;
path
+=
` A
${
radius
}
${
radius
}
0 0 0
${
turnX
}
${
next
.
y
}
`
;
path
+=
` L
${
next
.
x
}
${
next
.
y
}
`
;
}
}
else
{
path
+=
` L
${
next
.
x
}
${
next
.
y
}
`
;
}
}
const
last
=
timelineNodes
.
value
[
timelineNodes
.
value
.
length
-
1
];
if
(
last
.
row
%
2
===
0
)
{
path
+=
` L
${
last
.
x
+
400
}
${
last
.
y
}
`
;
}
else
{
path
+=
` L
${
last
.
x
-
100
}
${
last
.
y
}
`
;
}
return
path
;
});
const
svgWidth
=
computed
(()
=>
{
return
timelineContainerWidth
;
});
const
svgHeight
=
computed
(()
=>
{
const
rows
=
Math
.
ceil
(
timelineList
.
value
.
length
/
maxPerRow
);
console
.
log
(
"看下高度"
,
rows
);
return
startY
+
rows
*
rowHeight
+
50
;
});
const
fieldOptions
=
[
{
value
:
""
,
label
:
"全部领域"
},
{
value
:
"1"
,
label
:
"人工智能"
},
{
value
:
"2"
,
label
:
"生物科技"
},
{
value
:
"3"
,
label
:
"新一代信息技术"
},
{
value
:
"4"
,
label
:
"量子科技"
},
{
value
:
"5"
,
label
:
"新能源"
},
{
value
:
"6"
,
label
:
"集成电路"
},
{
value
:
"7"
,
label
:
"海洋"
},
{
value
:
"8"
,
label
:
"先进制造"
},
{
value
:
"9"
,
label
:
"新材料"
},
{
value
:
"10"
,
label
:
"航空航天"
},
{
value
:
"11"
,
label
:
"深海"
},
{
value
:
"12"
,
label
:
"极地"
},
{
value
:
"13"
,
label
:
"太空"
},
{
value
:
"14"
,
label
:
"核"
}
];
// 全领域统计
const
buttonsData
=
ref
([]);
const
bgList
=
[
{
text
:
"集成电路"
,
count
:
101
,
background
:
"linear-gradient(180.00deg, rgba(255, 102, 102, 1),rgba(255, 102, 102, 0.5) 100%)"
},
{
text
:
"人工智能"
,
count
:
132
,
background
:
"linear-gradient(180.00deg, rgba(51, 153, 255, 1),rgba(51, 153, 255, 0.5) 100%)"
},
{
text
:
"新一代信息技术"
,
count
:
105
,
background
:
"linear-gradient(180.00deg, rgba(255, 187, 51, 1),rgba(255, 187, 51, 0.5) 100%)"
},
{
text
:
"量子科技"
,
count
:
97
,
background
:
"linear-gradient(180.00deg, rgba(117, 73, 255, 1),rgba(117, 73, 255, 0.5) 100%)"
},
{
text
:
"先进制造"
,
count
:
84
,
background
:
"linear-gradient(180.00deg, rgba(102, 102, 102, 1),rgba(102, 102, 102, 0.5) 100%)"
},
{
text
:
"航空航天"
,
count
:
77
,
background
:
"linear-gradient(180.00deg, rgba(51, 102, 255, 1),rgba(51, 102, 255, 0.5) 100%)"
},
{
text
:
"生物科技"
,
count
:
62
,
background
:
"linear-gradient(180.00deg, rgba(102, 204, 204, 1),rgba(102, 204, 204, 0.5) 100%)"
},
{
text
:
"新能源"
,
count
:
60
,
background
:
"linear-gradient(180.00deg, rgba(102, 187, 51, 1),rgba(102, 187, 51, 0.5) 100%)"
},
{
text
:
"新材料"
,
count
:
43
,
background
:
"linear-gradient(180.00deg, rgba(255, 102, 51, 1),rgba(255, 102, 51, 0.5) 100%)"
},
{
text
:
"海洋"
,
count
:
25
,
background
:
"linear-gradient(180.00deg, rgba(153, 204, 255, 1),rgba(153, 204, 255, 0.5) 100%)"
},
{
text
:
"核"
,
count
:
25
,
background
:
"linear-gradient(180.00deg, rgba(255, 102, 102, 1),rgba(255, 102, 102, 0.5) 100%)"
},
{
text
:
"太空"
,
count
:
25
,
background
:
"linear-gradient(180.00deg, rgba(51, 153, 255, 1),rgba(51, 153, 255, 0.5) 100%)"
},
{
text
:
"其他"
,
count
:
25
,
background
:
"linear-gradient(180.00deg, rgba(255, 187, 51, 1),rgba(255, 187, 51, 0.5) 100%)"
},
{
text
:
"深海"
,
count
:
25
,
background
:
"linear-gradient(180.00deg, rgba(117, 73, 255, 1),rgba(117, 73, 255, 0.5) 100%)"
},
{
text
:
"极地"
,
count
:
25
,
background
:
"linear-gradient(180.00deg, rgba(102, 102, 102, 1),rgba(102, 102, 102, 0.5) 100%)"
},
{
text
:
"新一代通信网络"
,
count
:
25
,
background
:
"linear-gradient(180.00deg, rgba(153, 204, 255, 1),rgba(153, 204, 255, 0.5) 100%)"
}
];
const
getCalculatedDate
=
type
=>
{
const
now
=
new
Date
();
const
endDate
=
new
Date
();
const
start
=
new
Date
();
switch
(
type
)
{
case
"week"
:
// 近一个月
start
.
setMonth
(
now
.
getMonth
()
-
1
);
break
;
case
"three_month"
:
// 近三个月
start
.
setMonth
(
now
.
getMonth
()
-
3
);
break
;
case
"six_month"
:
// 近半年
start
.
setMonth
(
now
.
getMonth
()
-
6
);
break
;
case
"year"
:
// 近一年
start
.
setFullYear
(
now
.
getFullYear
()
-
1
);
break
;
default
:
start
.
setMonth
(
now
.
getMonth
()
-
1
);
// 默认近一个月
}
const
formatDate
=
date
=>
{
const
year
=
date
.
getFullYear
();
const
month
=
String
(
date
.
getMonth
()
+
1
).
padStart
(
2
,
"0"
);
const
day
=
String
(
date
.
getDate
()).
padStart
(
2
,
"0"
);
return
`
${
year
}
-
${
month
}
-
${
day
}
`
;
};
return
{
startDate
:
formatDate
(
start
),
endDate
:
formatDate
(
endDate
)
};
};
const
handleGetAllDomainCount
=
async
()
=>
{
try
{
const
{
startDate
,
endDate
}
=
getCalculatedDate
(
activeDate
.
value
);
const
res
=
await
getAllDomainCount
({
startDate
:
startDate
,
endDate
:
endDate
});
console
.
log
(
"全领域统计"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
// 按照 countNum 从大到小排序
res
.
data
.
sort
((
a
,
b
)
=>
b
.
countNum
-
a
.
countNum
);
buttonsData
.
value
=
res
.
data
.
map
((
item
,
index
)
=>
{
const
matchedBg
=
bgList
.
find
(
bg
=>
bg
.
text
===
item
.
countName
);
const
background
=
matchedBg
?
matchedBg
.
background
:
bgList
[
index
%
10
].
background
;
// 映射图标索引
let
iconIndex
=
0
;
// 默认
switch
(
item
.
countName
)
{
case
"集成电路"
:
iconIndex
=
0
;
break
;
case
"人工智能"
:
iconIndex
=
1
;
break
;
case
"新一代通信网络"
:
case
"新一代信息技术"
:
iconIndex
=
2
;
break
;
case
"量子科技"
:
iconIndex
=
3
;
break
;
case
"先进制造"
:
iconIndex
=
4
;
break
;
case
"航空航天"
:
iconIndex
=
5
;
break
;
case
"生物科技"
:
iconIndex
=
6
;
break
;
case
"新能源"
:
iconIndex
=
7
;
break
;
case
"新材料"
:
iconIndex
=
8
;
break
;
case
"海洋"
:
iconIndex
=
9
;
break
;
default
:
iconIndex
=
0
;
}
return
{
text
:
item
.
countName
,
count
:
item
.
countNum
,
background
:
background
,
originalIndex
:
iconIndex
};
});
const
chunkSize
=
2
;
buttonsData
.
value
=
Array
.
from
({
length
:
Math
.
ceil
(
buttonsData
.
value
.
length
/
chunkSize
)
},
(
_
,
i
)
=>
buttonsData
.
value
.
slice
(
i
*
chunkSize
,
i
*
chunkSize
+
chunkSize
)
);
console
.
log
(
"buttonsData"
,
buttonsData
.
value
);
startAutoPlay
();
}
}
catch
(
error
)
{}
};
const
box5Data
=
ref
({});
const
handleGetDomainContainmentTrend
=
async
()
=>
{
try
{
const
{
startDate
,
endDate
}
=
getCalculatedDate
(
activeDate
.
value
);
const
params
=
{
startDate
,
endDate
};
if
(
deptValue
.
value
)
{
params
.
org
=
deptValue
.
value
;
}
if
(
methodValue
.
value
)
{
params
.
sanMeasures
=
methodValue
.
value
;
}
const
res
=
await
getDomainContainmentTrend
(
params
);
console
.
log
(
"美对华领域打压遏制数量趋势"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
// 处理返回的数据结构,按照 mockdata.json 中的格式
const
processedData
=
processDomainTrendData
(
res
.
data
);
box5Data
.
value
=
processedData
;
// 更新图表
let
Chart
=
getMultiLineChart
(
box5Data
.
value
);
setChart
(
Chart
,
"chartRef"
);
}
}
catch
(
error
)
{
console
.
error
(
"获取美对华领域打压遏制数量趋势失败:"
,
error
);
}
};
// 处理领域趋势数据的方法
const
processDomainTrendData
=
rawData
=>
{
// 提取所有的月份作为标题
const
titles
=
rawData
.
map
(
item
=>
item
.
yearOrMonth
).
reverse
();
// 收集所有不重复的领域名称
const
domainNamesSet
=
new
Set
();
rawData
.
forEach
(
item
=>
{
item
.
domainList
.
forEach
(
domain
=>
{
domainNamesSet
.
add
(
domain
.
domainName
);
});
});
const
domainNames
=
Array
.
from
(
domainNamesSet
);
// 定义颜色映射
const
colorMap
=
{
人工智能
:
"#E34D59"
,
新一代通信网络
:
"#FF9F1C"
,
核
:
"#FFB3B3"
,
生物科技
:
"#00A79D"
,
量子科技
:
"#7B61FF"
,
先进制造
:
"#363B42"
,
新能源
:
"#2BA471"
,
太空
:
"#3762F0"
,
集成电路
:
"#0052D9"
,
新材料
:
"#FFD900"
,
航空航天
:
"#3762F0"
,
海洋
:
"#76D1FF"
,
深海
:
"#002060"
,
其他
:
"#A6A6A6"
};
// 生成数据系列
const
dataSeries
=
domainNames
.
map
(
domainName
=>
{
const
values
=
rawData
.
map
(
monthData
=>
{
const
domainItem
=
monthData
.
domainList
.
find
(
d
=>
d
.
domainName
===
domainName
);
return
domainItem
?
domainItem
.
domainNum
:
0
;
})
.
reverse
();
// 数据值也需要跟随标题反转顺序
return
{
name
:
domainName
,
color
:
colorMap
[
domainName
]
||
`#
${
Math
.
floor
(
Math
.
random
()
*
16777215
).
toString
(
16
)}
`
,
// 如果没有预定义颜色,则随机生成
value
:
values
};
});
return
{
title
:
titles
,
data
:
dataSeries
};
};
const
rankList
=
ref
([]);
const
maxCount
=
computed
(()
=>
{
if
(
!
rankList
.
value
||
rankList
.
value
.
length
===
0
)
return
0
;
return
Math
.
max
(...
rankList
.
value
.
map
(
item
=>
item
.
count
||
0
));
});
const
getProgressWidth
=
count
=>
{
if
(
!
maxCount
.
value
)
return
"0%"
;
return
(
count
/
maxCount
.
value
)
*
100
+
"%"
;
};
// 处理排名数据的方法
const
processRankingData
=
rawData
=>
{
if
(
!
rawData
||
!
Array
.
isArray
(
rawData
)
||
rawData
.
length
===
0
)
{
return
[];
}
return
rawData
.
map
(
item
=>
{
// 格式化日期:2025-10-08 -> 2025.10.8
let
formattedDate
=
""
;
if
(
item
.
sanctionDate
)
{
const
date
=
new
Date
(
item
.
sanctionDate
);
if
(
!
isNaN
(
date
.
getTime
()))
{
formattedDate
=
`
${
date
.
getFullYear
()}
.
${
date
.
getMonth
()
+
1
}
.
${
date
.
getDate
()}
`
;
}
else
{
formattedDate
=
item
.
sanctionDate
;
}
}
return
{
name
:
item
.
orgName
||
""
,
count
:
item
.
orgCount
||
0
,
orgPicture
:
item
.
orgPicture
,
// 新增字段
domains
:
item
.
domainList
?
item
.
domainList
.
map
(
d
=>
d
.
name
)
:
[],
date
:
formattedDate
,
member
:
item
.
keyMember
||
"-"
};
});
};
const
rankTypeMap
=
{
institution
:
"对我打压机构"
,
enterprise
:
"受打压企业"
,
school
:
"受打压院校"
};
// 获取领域遏制排名数据
const
handleGetDomainContainmentRanking
=
async
()
=>
{
rankLoading
.
value
=
true
;
rankList
.
value
=
[];
try
{
const
res
=
await
getDomainContainmentRanking
(
rankTypeMap
[
rankType
.
value
],
!!
selectedField
.
value
?
selectedField
.
value
:
""
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
// 处理返回的数据结构
const
processedData
=
processRankingData
(
res
.
data
);
rankList
.
value
=
processedData
;
}
}
catch
(
error
)
{
console
.
error
(
"获取美对华领域打压遏制排行失败:"
,
error
);
// 设置默认空数组
rankList
.
value
=
[];
}
finally
{
rankLoading
.
value
=
false
;
}
};
// 监听rankType变化, 调用获取领域遏制排名数据方法
watch
(
rankType
,
handleGetDomainContainmentRanking
);
// 监听selectedField变化, 调用获取领域遏制排名数据方法
watch
(
selectedField
,
handleGetDomainContainmentRanking
);
const
currentIndex
=
ref
(
0
);
let
autoTimer
=
null
;
const
visibleCount
=
7
;
const
cardWidth
=
215
;
// 卡片宽度
const
cardGap
=
16
;
// 卡片间距
const
startAutoPlay
=
isContiune
=>
{
if
(
!
isContiune
)
{
currentIndex
.
value
=
0
;
}
stopAutoPlay
();
if
(
buttonsData
.
value
.
length
>
visibleCount
)
{
autoTimer
=
setInterval
(()
=>
{
next
();
},
3000
);
}
};
const
stopAutoPlay
=
()
=>
{
if
(
autoTimer
)
{
clearInterval
(
autoTimer
);
autoTimer
=
null
;
}
};
const
next
=
()
=>
{
let
arr
=
[...
buttonsData
.
value
];
if
(
currentIndex
.
value
<
buttonsData
.
value
.
length
-
visibleCount
)
{
currentIndex
.
value
++
;
}
else
{
// currentIndex.value = 0;
buttonsData
.
value
=
[...
buttonsData
.
value
,
...
arr
];
currentIndex
.
value
++
;
}
};
const
prev
=
()
=>
{
if
(
currentIndex
.
value
>
0
)
{
currentIndex
.
value
--
;
}
else
{
currentIndex
.
value
=
Math
.
max
(
0
,
buttonsData
.
value
.
length
-
visibleCount
);
}
};
// const next = () => {
// const maxIndex = buttonsData.value.length - visibleCount;
// if (currentIndex.value
<
maxIndex
)
{
// currentIndex.value++;
// } else {
// // 滚动到末尾时,重置到开头并复制数组实现无缝滚动
// const arr = [...buttonsData.value];
// buttonsData.value = [...buttonsData.value, ...arr];
// currentIndex.value = buttonsData.value.length - visibleCount - arr.length;
// }
// };
// const prev = () => {
// if (currentIndex.value > 0) {
// currentIndex.value--;
// } else {
// // 滚动到开头时,跳转到末尾
// currentIndex.value = buttonsData.value.length - visibleCount;
// }
// };
const
handleTimeLineNode
=
node
=>
{
// console.log("timeLineNode", node);
if
(
node
.
eventType
===
"科技法案"
)
{
window
.
sessionStorage
.
setItem
(
"curTabName"
,
node
.
title
);
const
route
=
router
.
resolve
({
path
:
"/billLayout"
,
query
:
{
billId
:
node
.
eventId
}
});
window
.
open
(
route
.
href
,
"_blank"
);
}
};
onMounted
(()
=>
{
// let Chart = getMultiLineChart(box5Data.value);
// setChart(Chart, "chartRef");
handleGetDomainContainmentTrend
();
getDepartmentListData
();
handleGetSanList
();
handleGetAllDomainCount
();
handleGetDomainContainmentRanking
();
handleGetDomainContainmentTimeline
();
getUSGovernmentLatestDynamicData
();
startAutoPlay
();
});
onUnmounted
(()
=>
{
stopAutoPlay
();
});
watch
(
activeDate
,
()
=>
{
handleGetAllDomainCount
();
handleGetDomainContainmentTrend
();
});
</
script
>
<
style
lang=
"scss"
scoped
>
.content-wrapper
{
width
:
1666px
;
height
:
2132px
;
}
.btn-wrapper
{
position
:
relative
;
width
:
1601px
;
}
.cards-mask
{
width
:
100%
;
overflow
:
hidden
;
// 仅在这里隐藏超出部分,不影响外层的按钮
}
.btn-box
{
width
:
100%
;
width
:
max-content
;
height
:
176px
;
overflow
:
hidden
;
display
:
flex
;
flex-direction
:
row
;
flex-wrap
:
wrap
;
justify-content
:
flex-start
;
align-items
:
stretch
;
gap
:
16px
;
padding
:
0
;
transition
:
transform
0
.5s
ease
;
// 平滑过渡动画
}
.left-btn
{
width
:
24px
;
height
:
48px
;
position
:
absolute
;
top
:
50%
;
left
:
-33px
;
transform
:
translateY
(
-50%
);
cursor
:
pointer
;
z-index
:
10
;
}
.right-btn
{
width
:
24px
;
height
:
48px
;
position
:
absolute
;
top
:
50%
;
right
:
-33px
;
transform
:
translateY
(
-50%
);
cursor
:
pointer
;
z-index
:
10
;
}
.btn-item
{
/* 全领域-总统计 */
// width: 307px;
width
:
215px
;
height
:
80px
;
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
padding
:
0
16px
;
margin-bottom
:
10px
;
.btn-left-text
{
width
:
fit-content
;
min-width
:
60px
;
max-width
:
97px
;
height
:
60px
;
background-repeat
:
no-repeat
;
background-position
:
center
;
background-size
:
contain
;
font-family
:
YouSheBiaoTiHei
;
font-size
:
24px
;
font-weight
:
400
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
left
;
color
:
rgba
(
255
,
255
,
255
,
1
);
//换行
white-space
:
wrap
;
display
:
flex
;
align-items
:
center
;
font-style
:
italic
;
}
.btn-right
{
font-family
:
YouSheBiaoTiHei
;
font-size
:
30px
;
font-weight
:
400
;
color
:
rgba
(
255
,
255
,
255
,
1
);
font-style
:
italic
;
}
}
.btn-left
{
position
:
relative
;
display
:
flex
;
align-items
:
center
;
}
.btn-left-icon
{
margin-right
:
8px
;
// 图标和文本之间的间距
}
.main-charts
{
margin-top
:
16px
;
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
;
.charts-title
{
width
:
100%
;
height
:
54px
;
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
);
}
}
}
}
}
.title-right-select
{
width
:
150px
;
}
}
.charts-content
{
flex
:
1
;
width
:
100%
;
padding
:
20px
40px
20px
40px
;
box-sizing
:
border-box
;
.chart-container
{
width
:
100%
;
height
:
100%
;
}
}
}
.bottom-content
{
display
:
flex
;
gap
:
17px
;
background
:
rgba
(
255
,
255
,
255
,
0
.65
);
.news-section
{
width
:
792px
;
height
:
700px
;
.news-title
{
padding
:
8px
;
}
.tag-container
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
.tag-item
{
padding
:
2px
8px
;
border-radius
:
4px
;
font-size
:
14px
;
font-weight
:
400
;
font-family
:
"Microsoft YaHei"
;
border
:
1px
solid
transparent
;
&
.tag-blue
{
color
:
rgba
(
9
,
88
,
217
,
1
);
background
:
rgba
(
230
,
244
,
255
,
1
);
border-color
:
rgba
(
186
,
224
,
255
,
1
);
}
&
.tag-green
{
color
:
rgba
(
56
,
158
,
13
,
1
);
background
:
rgba
(
246
,
255
,
237
,
1
);
border-color
:
rgba
(
217
,
247
,
190
,
1
);
}
&
.tag-red
{
color
:
rgba
(
245
,
34
,
45
,
1
);
background
:
rgba
(
255
,
241
,
240
,
1
);
border-color
:
rgba
(
255
,
163
,
158
,
1
);
}
&
.tag-orange
{
color
:
rgba
(
250
,
140
,
22
,
1
);
background
:
rgba
(
255
,
247
,
230
,
1
);
border-color
:
rgba
(
255
,
213
,
145
,
1
);
}
&
.tag-purple
{
color
:
rgba
(
114
,
46
,
209
,
1
);
background
:
rgba
(
249
,
240
,
255
,
1
);
border-color
:
rgba
(
211
,
173
,
247
,
1
);
}
&
.tag-cyan
{
color
:
rgba
(
19
,
194
,
194
,
1
);
background
:
rgba
(
230
,
255
,
251
,
1
);
border-color
:
rgba
(
135
,
232
,
222
,
1
);
}
}
}
}
.empty-section
{
width
:
792px
;
height
:
700px
;
margin-top
:
16px
;
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
);
}
}
}
.select-box
{
width
:
691px
;
height
:
32px
;
margin
:
10px
auto
5px
auto
;
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
.rank-btns
{
display
:
flex
;
gap
:
8px
;
.rank-btn
{
padding
:
4px
12px
;
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
;
&
.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
:
#fff
;
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
);
}
}
}
}
}
}
.main-box
{
width
:
100%
;
height
:
577px
;
padding
:
24px
30px
0px
27px
;
box-sizing
:
border-box
;
display
:
flex
;
flex-direction
:
column
;
gap
:
28px
;
overflow-y
:
auto
;
.rank-item
{
display
:
flex
;
align-items
:
center
;
height
:
30px
;
flex-shrink
:
0
;
.rank-num
{
width
:
24px
;
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
margin-right
:
12px
;
text-align
:
center
;
color
:
#3b414b
;
&
.rank-1
{
color
:
#d94b4b
;
}
&
.rank-2
{
color
:
#e3935d
;
}
&
.rank-3
{
color
:
#ebd348
;
}
}
.rank-icon
{
width
:
30px
;
height
:
30px
;
margin-right
:
12px
;
}
.rank-name
{
width
:
180px
;
font-family
:
"Microsoft YaHei"
;
font-size
:
16px
;
font-weight
:
700
;
color
:
rgb
(
59
,
65
,
75
);
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
}
.rank-progress-container
{
flex
:
1
;
height
:
12px
;
margin
:
0
20px
;
background
:
transparent
;
display
:
flex
;
align-items
:
center
;
.rank-progress-bar
{
height
:
100%
;
border-radius
:
6px
;
background
:
linear-gradient
(
90deg
,
rgba
(
55
,
98
,
240
,
0
)
0%
,
rgba
(
55
,
98
,
240
,
0
.8
)
100%
);
}
}
&
:nth-child
(
1
)
.rank-progress-bar
{
background
:
linear-gradient
(
90deg
,
rgba
(
217
,
75
,
75
,
0
)
0%
,
rgba
(
217
,
75
,
75
,
0
.8
)
100%
);
}
&
:nth-child
(
2
)
.rank-progress-bar
{
background
:
linear-gradient
(
90deg
,
rgba
(
227
,
147
,
93
,
0
)
0%
,
rgba
(
227
,
147
,
93
,
0
.8
)
100%
);
}
&
:nth-child
(
3
)
.rank-progress-bar
{
background
:
linear-gradient
(
90deg
,
rgba
(
235
,
211
,
72
,
0
)
0%
,
rgba
(
235
,
211
,
72
,
0
.8
)
100%
);
}
.rank-count
{
width
:
60px
;
font-family
:
"Microsoft YaHei"
;
font-size
:
16px
;
font-weight
:
700
;
color
:
rgb
(
59
,
65
,
75
);
text-align
:
right
;
}
}
// 新增表格样式
.table-header
{
display
:
flex
;
align-items
:
center
;
padding-bottom
:
12px
;
// border-bottom: 1px solid #eee;
margin-bottom
:
8px
;
div
{
font-family
:
"Microsoft YaHei"
;
font-size
:
16px
;
color
:
#5f656c
;
font-weight
:
400
;
}
}
.table-list
{
flex
:
1
;
overflow-y
:
auto
;
display
:
flex
;
flex-direction
:
column
;
gap
:
16px
;
}
.table-row
{
display
:
flex
;
align-items
:
center
;
height
:
40px
;
.rank-num
{
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
text-align
:
center
;
color
:
#3b414b
;
&
.rank-1
{
color
:
#d94b4b
;
}
&
.rank-2
{
color
:
#e3935d
;
}
&
.rank-3
{
color
:
#ebd348
;
}
}
.flex-align
{
display
:
flex
;
align-items
:
center
;
}
.rank-icon
{
width
:
30px
;
height
:
30px
;
margin-right
:
12px
;
}
.text-ellipsis
{
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
font-family
:
"Microsoft YaHei"
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
30px
;
color
:
rgb
(
59
,
65
,
75
);
}
.domain-tags
{
display
:
flex
;
gap
:
6px
;
flex-wrap
:
wrap
;
.mini-tag
{
padding
:
2px
6px
;
border-radius
:
4px
;
font-size
:
12px
;
font-family
:
"Microsoft YaHei"
;
line-height
:
1
.2
;
white-space
:
nowrap
;
// 复用已有的tag颜色逻辑,需要配合 getTagClass
&
.tag-item
{
// 基础样式
}
&
.tag-blue
{
color
:
rgba
(
9
,
88
,
217
,
1
);
background
:
rgba
(
230
,
244
,
255
,
1
);
border-color
:
rgba
(
186
,
224
,
255
,
1
);
border
:
1px
solid
rgba
(
186
,
224
,
255
,
1
);
}
&
.tag-green
{
color
:
rgba
(
56
,
158
,
13
,
1
);
background
:
rgba
(
246
,
255
,
237
,
1
);
border-color
:
rgba
(
217
,
247
,
190
,
1
);
border
:
1px
solid
rgba
(
217
,
247
,
190
,
1
);
}
&
.tag-red
{
color
:
rgba
(
245
,
34
,
45
,
1
);
background
:
rgba
(
255
,
241
,
240
,
1
);
border-color
:
rgba
(
255
,
163
,
158
,
1
);
border
:
1px
solid
rgba
(
255
,
163
,
158
,
1
);
}
&
.tag-orange
{
color
:
rgba
(
250
,
140
,
22
,
1
);
background
:
rgba
(
255
,
247
,
230
,
1
);
border-color
:
rgba
(
255
,
213
,
145
,
1
);
border
:
1px
solid
rgba
(
255
,
213
,
145
,
1
);
}
&
.tag-purple
{
color
:
rgba
(
114
,
46
,
209
,
1
);
background
:
rgba
(
249
,
240
,
255
,
1
);
border-color
:
rgba
(
211
,
173
,
247
,
1
);
border
:
1px
solid
rgba
(
211
,
173
,
247
,
1
);
}
&
.tag-cyan
{
color
:
rgba
(
19
,
194
,
194
,
1
);
background
:
rgba
(
230
,
255
,
251
,
1
);
border-color
:
rgba
(
135
,
232
,
222
,
1
);
border
:
1px
solid
rgba
(
135
,
232
,
222
,
1
);
}
}
}
}
// 列宽控制
.col-rank
{
width
:
50px
;
text-align
:
center
;
flex-shrink
:
0
;
}
.col-name
{
flex
:
1
.5
;
min-width
:
0
;
margin-right
:
16px
;
}
.col-domain
{
flex
:
1
.5
;
min-width
:
0
;
margin-right
:
16px
;
}
.col-date
{
width
:
100px
;
flex-shrink
:
0
;
font-family
:
"Microsoft YaHei"
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
color
:
rgb
(
59
,
65
,
75
);
text-align
:
left
;
}
.col-member
{
width
:
80px
;
flex-shrink
:
0
;
font-family
:
"Microsoft YaHei"
;
font-size
:
16px
;
color
:
rgb
(
59
,
65
,
75
);
text-align
:
center
;
}
}
}
}
.news-content
{
overflow-y
:
auto
;
overflow-x
:
hidden
;
}
.news-item
{
/* 全政府-动态 (四全-最新动态) */
width
:
737px
;
height
:
124px
;
margin
:
0
28px
;
/* 自动布局 */
display
:
flex
;
flex-direction
:
column
;
justify-content
:
flex-start
;
align-items
:
flex-start
;
padding
:
16px
24px
16px
24px
;
box-sizing
:
border-box
;
border-bottom
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
background
:
transparent
;
.news-item-title
{
display
:
flex
;
justify-content
:
space-between
;
width
:
689px
;
.tag
{
display
:
none
;
}
.date
{
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
:
right
;
}
}
.content-title
{
cursor
:
pointer
;
width
:
689px
;
height
:
30px
;
/* 自动布局 */
display
:
flex
;
flex-direction
:
row
;
justify-content
:
flex-start
;
align-items
:
center
;
gap
:
12
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-style
:
Bold
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
.content-text
{
width
:
689px
;
height
:
30px
;
font-family
:
Microsoft
YaHei
;
font-style
:
Regular
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
left
;
color
:
rgba
(
59
,
65
,
75
,
1
);
margin-top
:
8px
;
/* 单行省略 */
display
:
-
webkit-box
;
-webkit-box-orient
:
vertical
;
-webkit-line-clamp
:
1
;
overflow
:
hidden
;
cursor
:
pointer
;
}
}
.line-time
{
margin-top
:
16px
;
width
:
1601px
;
height
:
700px
;
border-radius
:
10px
;
background-color
:
rgba
(
255
,
255
,
255
,
0
.65
);
box-shadow
:
0
0
20px
rgba
(
25
,
69
,
130
,
0
.1
);
position
:
relative
;
.left-btn
{
position
:
absolute
;
z-index
:
9999
;
left
:
0
;
top
:
345px
;
width
:
24px
;
height
:
48px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.right-btn
{
position
:
absolute
;
z-index
:
9999
;
right
:
0
;
top
:
345px
;
width
:
24px
;
height
:
48px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.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
);
}
}
.field-select
{
width
:
160px
;
:deep
(
.el-input
)
{
.el-input__wrapper
{
height
:
32px
;
padding
:
0
12px
;
box-sizing
:
border-box
;
background-color
:
#fff
;
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
);
}
}
}
}
}
}
.line-main
{
width
:
100%
;
height
:
652px
;
position
:
relative
;
.nav-btn
{
position
:
absolute
;
top
:
50%
;
transform
:
translateY
(
-50%
);
cursor
:
pointer
;
z-index
:
10
;
img
{
width
:
24px
;
height
:
48px
;
}
&
.left
{
left
:
0
;
}
&
.right
{
right
:
0
;
}
}
.svg-container
{
width
:
100%
;
height
:
100%
;
overflow
:
hidden
;
display
:
block
;
padding
:
0
;
box-sizing
:
border-box
;
}
.axis-date-label
{
background
:
rgba
(
231
,
243
,
255
,
1
);
padding
:
4px
2px
;
border-radius
:
8px
;
text-align
:
center
;
box-shadow
:
0
0
10px
rgba
(
0
,
0
,
0
,
0
.05
);
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
width
:
auto
;
min-width
:
60px
;
.year
,
.month
{
font-family
:
"Microsoft YaHei"
;
font-size
:
18px
;
font-weight
:
700
;
line-height
:
24px
;
color
:
rgb
(
5
,
95
,
194
);
margin-bottom
:
0
;
}
}
.timeline-content-item
{
width
:
100%
;
height
:
160px
;
display
:
flex
;
flex-direction
:
column
;
gap
:
8px
;
.item-tags
{
width
:
355px
;
height
:
30px
;
display
:
flex
;
gap
:
8px
;
overflow
:
auto
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
.tag-item
{
padding
:
2px
8px
;
border-radius
:
4px
;
font-size
:
14px
;
font-weight
:
400
;
font-family
:
"Microsoft YaHei"
;
border
:
1px
solid
transparent
;
// Ensure border width is set for all
&
.tag-blue
{
color
:
rgba
(
9
,
88
,
217
,
1
);
background
:
rgba
(
230
,
244
,
255
,
1
);
border-color
:
rgba
(
186
,
224
,
255
,
1
);
}
&
.tag-green
{
color
:
rgba
(
56
,
158
,
13
,
1
);
background
:
rgba
(
246
,
255
,
237
,
1
);
border-color
:
rgba
(
217
,
247
,
190
,
1
);
}
&
.tag-red
{
color
:
rgba
(
245
,
34
,
45
,
1
);
background
:
rgba
(
255
,
241
,
240
,
1
);
border-color
:
rgba
(
255
,
163
,
158
,
1
);
}
&
.tag-orange
{
color
:
rgba
(
250
,
140
,
22
,
1
);
background
:
rgba
(
255
,
247
,
230
,
1
);
border-color
:
rgba
(
255
,
213
,
145
,
1
);
}
&
.tag-purple
{
color
:
rgba
(
114
,
46
,
209
,
1
);
background
:
rgba
(
249
,
240
,
255
,
1
);
border-color
:
rgba
(
211
,
173
,
247
,
1
);
}
&
.tag-cyan
{
color
:
rgba
(
19
,
194
,
194
,
1
);
background
:
rgba
(
230
,
255
,
251
,
1
);
border-color
:
rgba
(
135
,
232
,
222
,
1
);
}
}
}
.item-title
{
font-size
:
18px
;
font-weight
:
700
;
color
:
rgb
(
59
,
65
,
75
);
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
width
:
100%
;
}
.item-desc
{
font-size
:
16px
;
font-weight
:
400
;
color
:
rgb
(
95
,
101
,
108
);
line-height
:
24px
;
/* max-height: 48px; 可选:明确限制高度 */
font-family
:
"Microsoft YaHei"
;
display
:
-
webkit-box
;
-webkit-box-orient
:
vertical
;
-webkit-line-clamp
:
2
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
cursor
:
pointer
;
white-space
:
normal
;
}
.el-tooltip__trigger
{
height
:
48px
;
}
.item-footer
{
font-size
:
16px
;
font-weight
:
400
;
color
:
rgb
(
95
,
101
,
108
);
line-height
:
24px
;
font-family
:
"Microsoft YaHei"
;
margin-top
:
4px
;
}
}
}
}
</
style
>
<
style
>
.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
;
}
.common-prompt-popper.el-popper
.el-popper__arrow
::before
{
background-color
:
rgb
(
59
,
65
,
75
)
!important
;
border-color
:
rgb
(
59
,
65
,
75
)
!important
;
}
</
style
>
src/views/ZMOverView/components/fourSuppress/components/addDomain/index.vue
浏览文件 @
4adeeffb
...
...
@@ -4,7 +4,7 @@
<div
class=
"content-wrapper"
>
<div
class=
"btn-wrapper"
@
mouseenter=
"stopAutoPlay"
@
mouseleave=
"startAutoPlay(true)"
>
<div
class=
"cards-mask"
>
<div
class=
"btn-box"
:style=
"
{ transform: `translateX(-${currentIndex * (
307 + 16
)}px)` }">
<div
class=
"btn-box"
:style=
"
{ transform: `translateX(-${currentIndex * (
cardWidth + cardGap
)}px)` }">
<div
class=
"btn-item-outer"
v-for=
"(item, indexx) in buttonsData"
:key=
"indexx"
>
<div
v-for=
"(value, index) in item"
...
...
@@ -73,15 +73,20 @@
<img
src=
"./icon/icon-2.png"
alt=
""
style=
"width: 22px; height: 18px"
/>
<span>
美对华领域打压遏制最新动态
</span>
</div>
<div
class=
"title-right-select"
>
<el-select
v-model=
"selectedFieldForLatest"
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=
"news-content"
>
<div
v-for=
"
value,idx in n
ewsList"
:key=
"idx"
class=
"news-item"
>
<div
v-for=
"
(value, idx) in paginatedN
ewsList"
:key=
"idx"
class=
"news-item"
>
<div
class=
"news-item-title"
>
<div
class=
"tag-container"
>
<!--
<div
v-for=
"tag in value.tags"
:key=
"tag"
:class=
"getTagClass(tag)"
>
{{
tag
}}
</div>
-->
<AreaTag
v-for=
"
tag,index
in value.tags"
:key=
"index"
:tagName=
"tag"
></AreaTag>
<AreaTag
v-for=
"
(tag, index)
in value.tags"
:key=
"index"
:tagName=
"tag"
></AreaTag>
</div>
<div
class=
"date"
>
...
...
@@ -104,6 +109,16 @@
</el-tooltip>
</div>
</div>
<div
class=
"news-pagination"
>
<el-pagination
layout=
"prev, pager, next"
:total=
"newsList.length"
:page-size=
"newsPageSize"
v-model:current-page=
"newsCurrentPage"
size=
"small"
@
current-change=
"handleNewsPageChange"
/>
</div>
</div>
<div
class=
"empty-section"
>
<div
class=
"bottom-item"
>
...
...
@@ -213,7 +228,7 @@
</marker>
</defs>
<path
:d=
"snakePath"
fill=
"none"
stroke=
"
#e8f2ff"
stroke-width=
"2
"
/>
<path
:d=
"snakePath"
fill=
"none"
stroke=
"
rgba(185, 220, 255, 1)"
stroke-width=
"5
"
/>
<g
v-for=
"(label, index) in axisDates"
:key=
"'date-' + index"
>
<foreignObject
:x=
"label.x"
:y=
"label.y"
width=
"80"
height=
"60"
style=
"overflow: visible"
>
...
...
@@ -239,7 +254,7 @@
<div
class=
"timeline-content-item"
>
<div
class=
"item-tags"
>
<!-- <span v-for="tag in node.tags" :key="tag" :class="getTagClass(tag)">{{ tag }}</span> -->
<AreaTag
v-for=
"
tag,idx
in node.tags"
:key=
"idx"
:tagName=
"tag"
></AreaTag>
<AreaTag
v-for=
"
(tag, idx)
in node.tags"
:key=
"idx"
:tagName=
"tag"
></AreaTag>
</div>
<div
class=
"item-title"
>
<CommonPrompt
:content=
"node.title"
/>
...
...
@@ -261,10 +276,10 @@
</div>
</div>
<div
class=
"left-btn"
@
click=
"handleLeft"
>
<img
src=
"@/assets/icons/card-btn-left.png"
alt=
""
>
<img
src=
"@/assets/icons/card-btn-left.png"
alt=
""
/
>
</div>
<div
class=
"right-btn"
@
click=
"handleRight"
>
<img
src=
"@/assets/icons/card-btn-right.png"
alt=
""
>
<img
src=
"@/assets/icons/card-btn-right.png"
alt=
""
/
>
</div>
</div>
</div>
...
...
@@ -366,11 +381,25 @@ watch(
const
rankType
=
ref
(
"institution"
);
const
rankLoading
=
ref
(
false
);
const
selectedField
=
ref
(
""
);
const
selectedFieldForLatest
=
ref
(
""
);
const
selectedFieldTimeline
=
ref
(
""
);
const
timelineContainerWidth
=
1700
;
// 美政府部门打压遏制最新动态
const
newsList
=
ref
([]);
const
newsCurrentPage
=
ref
(
1
);
const
newsPageSize
=
ref
(
5
);
// 每页显示 5 条
// 分页后的新闻列表
const
paginatedNewsList
=
computed
(()
=>
{
const
start
=
(
newsCurrentPage
.
value
-
1
)
*
newsPageSize
.
value
;
const
end
=
start
+
newsPageSize
.
value
;
return
newsList
.
value
.
slice
(
start
,
end
);
});
const
handleNewsPageChange
=
page
=>
{
newsCurrentPage
.
value
=
page
;
};
const
getUSGovernmentLatestDynamicData
=
async
()
=>
{
try
{
...
...
@@ -417,18 +446,26 @@ const processTimelineData = rawData => {
}
return
rawData
.
map
(
item
=>
{
// 将日期格式转换为 "YYYY年 M月" 格式
const
eventDate
=
item
.
eventDate
?
new
Date
(
item
.
eventDate
)
:
null
;
const
formattedDate
=
eventDate
?
`
${
eventDate
.
getFullYear
()}
年
${
eventDate
.
getMonth
()
+
1
}
月`
:
""
;
// 提取领域标签
const
tags
=
[];
let
tags
=
[];
if
(
item
.
eventDomainList
&&
Array
.
isArray
(
item
.
eventDomainList
))
{
item
.
eventDomainList
.
forEach
(
domain
=>
{
if
(
domain
.
domainName
)
{
tags
.
push
(
domain
.
domainName
);
if
(
!
selectedFieldTimeline
.
value
)
{
tags
=
item
.
eventDomainList
.
slice
(
0
,
3
).
map
(
domain
=>
domain
.
domainName
||
""
);
}
else
{
const
matchedIndex
=
item
.
eventDomainList
.
findIndex
(
domain
=>
domain
.
domainId
===
selectedFieldTimeline
.
value
);
if
(
matchedIndex
!==
-
1
)
{
const
matchedItem
=
item
.
eventDomainList
[
matchedIndex
];
const
remainingItems
=
item
.
eventDomainList
.
filter
((
_
,
idx
)
=>
idx
!==
matchedIndex
);
const
sortedList
=
[
matchedItem
,
...
remainingItems
];
tags
=
sortedList
.
slice
(
0
,
3
).
map
(
domain
=>
domain
.
domainName
||
""
);
}
else
{
tags
=
item
.
eventDomainList
.
slice
(
0
,
3
).
map
(
domain
=>
domain
.
domainName
||
""
);
}
}
);
}
}
return
{
...
...
@@ -437,7 +474,6 @@ const processTimelineData = rawData => {
title
:
item
.
eventName
||
""
,
content
:
item
.
eventDesc
||
""
,
info
:
`
${
item
.
eventDate
||
""
}
·
${
item
.
eventType
||
""
}
`
,
// 保留原始数据字段
eventId
:
item
.
eventId
,
eventOrg
:
item
.
eventOrg
,
eventType
:
item
.
eventType
,
...
...
@@ -454,15 +490,35 @@ const handleGetDomainContainmentTimeline = async () => {
if
(
selectedFieldTimeline
.
value
)
{
params
.
domain
=
selectedFieldTimeline
.
value
;
}
console
.
log
(
"美对我领域打压遏制时间线"
,
params
);
const
res
=
await
getDomainContainmentTimeline
(
params
);
console
.
log
(
"美对我领域打压遏制时间线"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
// 处理返回的数据结构
const
processedData
=
processTimelineData
(
res
.
data
);
// processedData.forEach(item => {
// if (item.eventDomainList && Array.isArray(item.eventDomainList)) {
// if (!selectedFieldTimeline.value) {
// item.eventDomainList = item.eventDomainList.slice(0, 3);
// } else {
// const matchedIndex = item.eventDomainList.findIndex(
// domain => domain.domainId === selectedFieldTimeline.value
// );
// if (matchedIndex !== -1) {
// const matchedItem = item.eventDomainList[matchedIndex];
// const remainingItems = item.eventDomainList.filter((_, idx) => idx !== matchedIndex);
// item.eventDomainList = [matchedItem, ...remainingItems.slice(0, 2)];
// } else {
// item.eventDomainList = item.eventDomainList.slice(0, 3);
// }
// }
// }
// });
timelineList
.
value
=
processedData
;
console
.
log
(
'timelineList'
,
timelineList
.
value
);
console
.
log
(
"timelineList"
,
timelineList
.
value
);
}
}
catch
(
error
)
{
console
.
error
(
"获取美对我领域打压遏制时间线失败:"
,
error
);
...
...
@@ -477,10 +533,9 @@ const rowHeight = 230;
const
startX
=
250
;
const
startY
=
45
;
const
timeLineActiveIndex
=
ref
(
0
)
const
timeLineActiveIndex
=
ref
(
0
)
;
const
axisDates
=
computed
(()
=>
{
const
dates
=
[];
if
(
timelineList
.
value
.
length
>
0
)
{
dates
.
push
({
...
...
@@ -500,39 +555,37 @@ const axisDates = computed(() => {
y
:
lastNode
.
y
-
25
});
}
return
dates
return
dates
;
});
const
handleLeft
=
()
=>
{
if
(
timeLineActiveIndex
.
value
===
0
)
{
ElMessage
.
warning
(
'当前已经是第一组数据!'
)
if
(
timeLineActiveIndex
.
value
===
0
)
{
ElMessage
.
warning
(
"当前已经是第一组数据!"
);
}
else
{
timeLineActiveIndex
.
value
--
timeLineActiveIndex
.
value
--
;
}
}
}
;
const
handleRight
=
()
=>
{
if
(
timeLineActiveIndex
.
value
===
(
timelineList
.
value
.
length
%
9
)
)
{
ElMessage
.
warning
(
'当前已经是最后一组数据!'
)
if
(
timeLineActiveIndex
.
value
===
timelineList
.
value
.
length
%
9
)
{
ElMessage
.
warning
(
"当前已经是最后一组数据!"
);
}
else
{
timeLineActiveIndex
.
value
++
timeLineActiveIndex
.
value
++
;
}
console
.
log
(
'axisDates'
,
axisDates
.
value
);
console
.
log
(
'timelineNodes'
,
timelineNodes
.
value
);
}
console
.
log
(
"axisDates"
,
axisDates
.
value
);
console
.
log
(
"timelineNodes"
,
timelineNodes
.
value
);
};
const
timelineNodes
=
computed
(()
=>
{
// 计算起始索引:activeIndex * 9
const
startIndex
=
timeLineActiveIndex
.
value
*
9
;
// 计算结束索引:起始索引 + 9(因为slice的第二个参数是结束索引,不包含)
const
endIndex
=
timeLineActiveIndex
.
value
+
9
;
const
startIndex
=
timeLineActiveIndex
.
value
*
9
;
const
showTimeLineList
=
timelineList
.
value
.
slice
(
startIndex
,
endIndex
);
// 计算结束索引:起始索引 + 9(因为slice的第二个参数是结束索引,不包含)
const
endIndex
=
timeLineActiveIndex
.
value
+
9
;
const
showTimeLineList
=
timelineList
.
value
.
slice
(
startIndex
,
endIndex
);
console
.
log
(
"时间线相关数据 showTimeLineList =>"
,
showTimeLineList
);
console
.
log
(
"时间线相关数据 timelineList =>"
,
timelineList
.
value
);
return
showTimeLineList
.
map
((
item
,
index
)
=>
{
const
row
=
Math
.
floor
(
index
/
maxPerRow
);
const
col
=
index
%
maxPerRow
;
...
...
@@ -560,7 +613,7 @@ const timelineNodes = computed(() => {
contentWidth
:
320
,
contentHeight
:
180
};
})
})
;
});
const
getColorName
=
tag
=>
{
...
...
@@ -1012,6 +1065,9 @@ watch(selectedField, handleGetDomainContainmentRanking);
const
currentIndex
=
ref
(
0
);
let
autoTimer
=
null
;
const
visibleCount
=
7
;
const
cardWidth
=
215
;
// 卡片宽度
const
cardGap
=
16
;
// 卡片间距
const
startAutoPlay
=
isContiune
=>
{
if
(
!
isContiune
)
{
...
...
@@ -1019,7 +1075,7 @@ const startAutoPlay = isContiune => {
}
stopAutoPlay
();
if
(
buttonsData
.
value
.
length
>
5
)
{
if
(
buttonsData
.
value
.
length
>
visibleCount
)
{
autoTimer
=
setInterval
(()
=>
{
next
();
},
3000
);
...
...
@@ -1035,7 +1091,7 @@ const stopAutoPlay = () => {
const
next
=
()
=>
{
let
arr
=
[...
buttonsData
.
value
];
if
(
currentIndex
.
value
<
buttonsData
.
value
.
length
-
5
)
{
if
(
currentIndex
.
value
<
buttonsData
.
value
.
length
-
visibleCount
)
{
currentIndex
.
value
++
;
}
else
{
// currentIndex.value = 0;
...
...
@@ -1048,10 +1104,32 @@ const prev = () => {
if
(
currentIndex
.
value
>
0
)
{
currentIndex
.
value
--
;
}
else
{
currentIndex
.
value
=
Math
.
max
(
0
,
buttonsData
.
value
.
length
-
5
);
currentIndex
.
value
=
Math
.
max
(
0
,
buttonsData
.
value
.
length
-
visibleCount
);
}
};
// const next = () => {
// const maxIndex = buttonsData.value.length - visibleCount;
// if (currentIndex.value
<
maxIndex
)
{
// currentIndex.value++;
// } else {
// // 滚动到末尾时,重置到开头并复制数组实现无缝滚动
// const arr = [...buttonsData.value];
// buttonsData.value = [...buttonsData.value, ...arr];
// currentIndex.value = buttonsData.value.length - visibleCount - arr.length;
// }
// };
// const prev = () => {
// if (currentIndex.value > 0) {
// currentIndex.value--;
// } else {
// // 滚动到开头时,跳转到末尾
// currentIndex.value = buttonsData.value.length - visibleCount;
// }
// };
const
handleTimeLineNode
=
node
=>
{
// console.log("timeLineNode", node);
if
(
node
.
eventType
===
"科技法案"
)
{
...
...
@@ -1144,7 +1222,8 @@ watch(activeDate, () => {
.btn-item
{
/* 全领域-总统计 */
width
:
307px
;
// width: 307px;
width
:
215px
;
height
:
80px
;
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
...
...
@@ -1156,6 +1235,7 @@ watch(activeDate, () => {
.btn-left-text
{
width
:
fit-content
;
min-width
:
60px
;
max-width
:
97px
;
height
:
60px
;
background-repeat
:
no-repeat
;
background-position
:
center
;
...
...
@@ -1163,19 +1243,19 @@ watch(activeDate, () => {
font-family
:
YouSheBiaoTiHei
;
font-size
:
24px
;
font-weight
:
400
;
line-height
:
6
0px
;
line-height
:
3
0px
;
letter-spacing
:
0px
;
text-align
:
left
;
color
:
rgba
(
255
,
255
,
255
,
1
);
//
不
换行
white-space
:
no
wrap
;
//换行
white-space
:
wrap
;
display
:
flex
;
align-items
:
center
;
font-style
:
italic
;
}
.btn-right
{
font-family
:
YouSheBiaoTiHei
;
font-size
:
24
px
;
font-size
:
30
px
;
font-weight
:
400
;
color
:
rgba
(
255
,
255
,
255
,
1
);
font-style
:
italic
;
...
...
@@ -1204,7 +1284,7 @@ watch(activeDate, () => {
.charts-title
{
width
:
100%
;
height
:
48
px
;
height
:
54
px
;
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
...
...
@@ -1276,6 +1356,10 @@ watch(activeDate, () => {
}
}
}
.title-right-select
{
width
:
150px
;
}
}
.charts-content
{
...
...
@@ -1298,11 +1382,71 @@ watch(activeDate, () => {
.news-section
{
width
:
792px
;
height
:
700px
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-between
;
.news-title
{
padding
:
8px
;
}
.news-pagination
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
padding
:
16px
0
;
:deep
(
.el-pagination
)
{
&
.is-background
.el-pager
li
{
background-color
:
#fff
;
border
:
1px
solid
#dcdfe6
;
border-radius
:
4px
;
font-size
:
14px
;
min-width
:
32px
;
height
:
32px
;
line-height
:
32px
;
margin
:
0
4px
;
&
.is-active
{
background-color
:
#055fc2
;
color
:
#fff
;
border-color
:
#055fc2
;
}
&
:hover
{
background-color
:
#f5f7fa
;
}
}
.btn-prev
,
.btn-next
{
background-color
:
rgba
(
231
,
243
,
255
,
1
);
// border: 1px solid #dcdfe6;
border
:
none
;
border-radius
:
4px
;
font-size
:
14px
;
// min-width: 32px;
// height: 32px;
line-height
:
32px
;
margin-right
:
4px
;
.el-icon
{
font-size
:
16px
;
color
:
#055fc2
;
font-weight
:
800
;
}
&
:hover:not
(
.is-disabled
)
{
background-color
:
#f5f7fa
;
}
&
.is-disabled
{
opacity
:
0
.5
;
cursor
:
not
-
allowed
;
}
}
}
}
.tag-container
{
display
:
flex
;
align-items
:
center
;
...
...
@@ -1692,11 +1836,12 @@ watch(activeDate, () => {
.news-content
{
overflow-y
:
auto
;
overflow-x
:
hidden
;
margin-bottom
:
auto
;
}
.news-item
{
/* 全政府-动态 (四全-最新动态) */
width
:
737px
;
height
:
1
24
px
;
height
:
1
16
px
;
margin
:
0
28px
;
/* 自动布局 */
display
:
flex
;
...
...
@@ -1764,7 +1909,7 @@ watch(activeDate, () => {
letter-spacing
:
0px
;
text-align
:
left
;
color
:
rgba
(
59
,
65
,
75
,
1
);
margin-top
:
8px
;
//
margin-top: 8px;
/* 单行省略 */
display
:
-
webkit-box
;
-webkit-box-orient
:
vertical
;
...
...
@@ -1783,27 +1928,27 @@ watch(activeDate, () => {
box-shadow
:
0
0
20px
rgba
(
25
,
69
,
130
,
0
.1
);
position
:
relative
;
.left-btn
{
.left-btn
{
position
:
absolute
;
z-index
:
9999
;
left
:
0
;
top
:
345px
;
width
:
24px
;
height
:
48px
;
img
{
img
{
width
:
100%
;
height
:
100%
;
}
}
.right-btn
{
.right-btn
{
position
:
absolute
;
z-index
:
9999
;
right
:
0
;
top
:
345px
;
width
:
24px
;
height
:
48px
;
img
{
img
{
width
:
100%
;
height
:
100%
;
}
...
...
src/views/ZMOverView/components/fourSuppress/components/addDomain/mockdata.json
deleted
100644 → 0
浏览文件 @
ab0482ce
{
"code"
:
200
,
"message"
:
"操作成功"
,
"success"
:
true
,
"data"
:
[
{
"eventType"
:
"行政令"
,
"eventName"
:
"为了美国和委内瑞拉人民的利益保障委内瑞拉的石油收入"
,
"eventDesc"
:
null
,
"eventId"
:
"248914"
,
"eventDomainList"
:
[
{
"domainId"
:
"1"
,
"domainName"
:
"人工智能"
},
{
"domainId"
:
"3"
,
"domainName"
:
"新一代通信网络"
}
],
"eventOrgName"
:
null
,
"eventDate"
:
"2026-01-10"
},
{
"eventType"
:
"行政令"
,
"eventName"
:
null
,
"eventDesc"
:
null
,
"eventId"
:
"248863"
,
"eventDomainList"
:
[
{
"domainId"
:
"8"
,
"domainName"
:
"先进制造"
},
{
"domainId"
:
"9"
,
"domainName"
:
"新材料"
}
],
"eventOrgName"
:
null
,
"eventDate"
:
"2026-01-09"
},
{
"eventType"
:
"行政令"
,
"eventName"
:
"使美国退出与美国利益相悖的国际组织、公约、条约"
,
"eventDesc"
:
null
,
"eventId"
:
"249004"
,
"eventDomainList"
:
[
{
"domainId"
:
"2"
,
"domainName"
:
"生物科技"
},
{
"domainId"
:
"4"
,
"domainName"
:
"量子科技"
},
{
"domainId"
:
"5"
,
"domainName"
:
"新能源"
},
{
"domainId"
:
"3"
,
"domainName"
:
"新一代通信网络"
}
],
"eventOrgName"
:
null
,
"eventDate"
:
"2026-01-08"
},
{
"eventType"
:
"行政令"
,
"eventName"
:
"在国防合同中优先考虑作战人员"
,
"eventDesc"
:
null
,
"eventId"
:
"248915"
,
"eventDomainList"
:
[
{
"domainId"
:
"99"
,
"domainName"
:
"其他"
},
{
"domainId"
:
"8"
,
"domainName"
:
"先进制造"
},
{
"domainId"
:
"10"
,
"domainName"
:
"航空航天"
}
],
"eventOrgName"
:
null
,
"eventDate"
:
"2026-01-08"
},
{
"eventType"
:
"行政令"
,
"eventName"
:
"大西洋高度洄游物种;商业性大西洋黑鼻鲨和娱乐性大西洋鲨鱼渔业管理措施的修订"
,
"eventDesc"
:
"NMFS提议对商业和休闲大西洋鲨鱼渔业进行几项改革。具体来说,NMFS正在考虑取消大西洋地区黑鼻鲨管理边界,修改商业保留限额..."
,
"eventId"
:
"163447"
,
"eventDomainList"
:
[
{
"domainId"
:
"14"
,
"domainName"
:
"核"
},
{
"domainId"
:
"7"
,
"domainName"
:
"海洋"
}
],
"eventOrgName"
:
null
,
"eventDate"
:
"2026-01-05"
},
{
"eventType"
:
"行政令"
,
"eventName"
:
"关于Hiefo Corporation收购Emcore Corporation部分资产"
,
"eventDesc"
:
null
,
"eventId"
:
"248916"
,
"eventDomainList"
:
[
{
"domainId"
:
"3"
,
"domainName"
:
"新一代通信网络"
},
{
"domainId"
:
"8"
,
"domainName"
:
"先进制造"
},
{
"domainId"
:
"6"
,
"domainName"
:
"集成电路"
}
],
"eventOrgName"
:
null
,
"eventDate"
:
"2026-01-03"
},
{
"eventType"
:
"行政令"
,
"eventName"
:
"汽车贷款利息扣除"
,
"eventDesc"
:
"本文件包含关于某些纳税人扣除高达10,000美元的合格乘用车贷款利息的拟议法规。本文件还包含关于新信息报告的拟议法规..."
,
"eventId"
:
"163443"
,
"eventDomainList"
:
[
{
"domainId"
:
"13"
,
"domainName"
:
"太空"
},
{
"domainId"
:
"14"
,
"domainName"
:
"核"
}
],
"eventOrgName"
:
null
,
"eventDate"
:
"2026-01-02"
},
{
"eventType"
:
"行政令"
,
"eventName"
:
"品牌处方药费用法规的法定更新"
,
"eventDesc"
:
"本文件建议修订有关对从事制造或进口某些品牌处方药业务的相关实体征收年费的法规。为了应对覆盖缺口折扣的替代..."
,
"eventId"
:
"163444"
,
"eventDomainList"
:
[
{
"domainId"
:
"2"
,
"domainName"
:
"生物科技"
},
{
"domainId"
:
"3"
,
"domainName"
:
"新一代通信网络"
}
],
"eventOrgName"
:
null
,
"eventDate"
:
"2026-01-02"
},
{
"eventType"
:
"337"
,
"eventName"
:
"外国制造的半导体器件及其下游产品和组件"
,
"eventDesc"
:
"美国ITC发布对外国制造的半导体器件及其下游产品和组件的337部分终裁"
,
"eventId"
:
"111"
,
"eventDomainList"
:
[
{
"domainId"
:
"1"
,
"domainName"
:
"人工智能"
},
{
"domainId"
:
"5"
,
"domainName"
:
"新能源"
}
],
"eventOrgName"
:
"美国商务部"
,
"eventDate"
:
"2026-01-01"
},
{
"eventType"
:
"行政令"
,
"eventName"
:
"美国东北部的渔业;大西洋冲浪蛤和海洋圆蛤渔业管理计划修正案21"
,
"eventDesc"
:
"NMFS宣布,中大西洋渔业管理委员会已提交大西洋冲浪蛤和海洋圆蛤渔业管理计划第21号修正案,供商务部长审查和批准。我们正在征求意见..."
,
"eventId"
:
"163426"
,
"eventDomainList"
:
[
{
"domainId"
:
"7"
,
"domainName"
:
"海洋"
},
{
"domainId"
:
"3"
,
"domainName"
:
"新一代通信网络"
}
],
"eventOrgName"
:
null
,
"eventDate"
:
"2025-12-29"
}
]
}
\ No newline at end of file
src/views/ZMOverView/components/fourSuppress/index.vue
浏览文件 @
4adeeffb
...
...
@@ -26,7 +26,7 @@
<
script
setup
>
import
{
onMounted
,
ref
,
computed
}
from
"vue"
;
import
right
from
"./assets/right.png"
;
import
right
from
"./assets/right
-white
.png"
;
import
background
from
"./assets/background.png"
;
// 组件引入
...
...
@@ -104,12 +104,13 @@ const handleNavClick = name => {
}
&
.active
{
background-color
:
rgba
(
246
,
250
,
255
,
1
);
background-color
:
rgba
(
5
,
95
,
194
,
1
);
border
:
1px
solid
rgba
(
174
,
214
,
255
,
1
);
border-radius
:
10px
;
span
{
color
:
rgb
(
5
,
95
,
194
);
// color: rgb(5, 95, 194);
color
:
#fff
;
}
}
}
...
...
src/views/ZMOverView/index.vue
浏览文件 @
4adeeffb
...
...
@@ -21,8 +21,13 @@
<!-- 美对华“四全”打压 -->
<div
id=
"us-pressure"
class=
"us-pressure-section"
>
<div
class=
"data-select"
>
<div
v-for=
"item in dateList"
:key=
"item.type"
class=
"date-item"
:class=
"
{ active: activeDate === item.type }"
@click="handleDateClick(item.type)">
<div
v-for=
"item in dateList"
:key=
"item.type"
class=
"date-item"
:class=
"
{ active: activeDate === item.type }"
@click="handleDateClick(item.type)"
>
<!--
<img
:src=
"activeDate === item.type ? item.activeIcon : item.icon"
alt=
""
/>
-->
<span>
{{
item
.
name
}}
</span>
</div>
...
...
@@ -133,8 +138,6 @@ provide("activeDate", activeDate);
const
handleDateClick
=
type
=>
{
activeDate
.
value
=
type
;
};
</
script
>
<
style
lang=
"scss"
scoped
>
...
...
@@ -250,7 +253,8 @@ const handleDateClick = type => {
.home-top-bg
{
background
:
url("./assets/images/background.png")
,
linear-gradient
(
180deg
,
rgba
(
229
,
241
,
254
,
1
)
0%
,
rgba
(
246
,
251
,
255
,
0
)
30%
);
url("./assets/images/background.png")
,
linear-gradient
(
180deg
,
rgba
(
229
,
241
,
254
,
1
)
0%
,
rgba
(
246
,
251
,
255
,
0
)
30%
);
background-size
:
100%
100%
;
position
:
absolute
;
width
:
100%
;
...
...
@@ -266,7 +270,7 @@ const handleDateClick = type => {
.data-select
{
width
:
108px
;
height
:
192px
;
position
:
fixed
;
position
:
absolute
;
top
:
149px
;
left
:
0
;
background-color
:
rgba
(
255
,
255
,
255
,
0
.65
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论