提交 56cf0ae3 authored 作者: coderBryanFu's avatar coderBryanFu

update

import request from "@/api/request.js";
// 规则限制-首页统计接口
export function getStatCount() {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/statCount`
})
}
// 规则限制-查询最新动态接口
export function getLatestUpdates() {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getLatestUpdates`
})
}
// 规则限制-风险信号
export function getRiskSignal(params) {
return request({
method: 'GET',
url: `/api/commonFeature/riskSignal/${params}`
})
}
// 规则限制-查询新闻资讯
export function getNews(params) {
return request({
method: 'GET',
url: `/api/commonFeature/news/${params}`
})
}
// 规则限制-查询社交媒体
export function getRemarks(params) {
return request({
method: 'GET',
url: `/api/commonFeature/remarks/${params}`
})
}
// 规则限制-限制领域分布情况
/**
* @param {Object} params
* @param {string} params.year
* @header token
*/
export function getAreaDistribution(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getAreaDistribution`,
params
})
}
// 规则限制-受限实体数量变化趋势
/**
* @param {Object} params
* @param {Integer} params.year
* @param {String} params.type
* @header token
*/
export function getEntityChangeTrend(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getEntityChangeTrend`,
params
})
}
// 规则限制-规则限制政令列表查询接口
/**
* @param {Object} params
* @param {Integer} params.currentPage
* @param {Integer} params.pageSize
* @param {List<String>} params.years
* @param {List<String>} params.areas
* @param {String} params.keywords
* @param {String} params.sortField
* @param {String} params.sortOrder
* @header token
*/
export function getRuleLimitList(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getRuleLimitList`,
params
})
}
// 规则限制-排华科技联盟列表接口
/**
* @param {Object} params
* @param {Integer} params.currentPage
* @param {Integer} params.pageSize
* @param {List<String>} params.years
* @param {List<String>} params.countries
* @param {List<String>} params.areas
* @param {String} params.keywords
* @param {String} params.sortField
* @param {String} params.sortOrder
* @header token
*/
export function getACTAList(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getACTAList`,
params
})
}
export function getAcTAAllcountry() {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getACTAAllCountry/`
})
}
// 规则限制-规则限制基本详情
export function getSanctionOverview(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getSanctionOverview/${params}`
})
}
// 实体清单-制裁概况-获取发布机构机构动态
/**
* @param {Object} data
* @param {string} data.orgId
* @header token
*/
export function getPublishOrgInfo(data) {
return request({
method: 'POST',
url: `/api/organization/relate/news`,
data,
})
}
\ No newline at end of file
......@@ -106,7 +106,8 @@ const getMainDataList = async () => {
params.sortOrder = value.value;
}
try {
try {
console.log('----params getMainDataList', params)
const res = await getCoopRestrictionList(params);
if (res && res.code === 200) {
mainDataList.value = (res.data.content || []).map(item => ({
......
......@@ -161,26 +161,26 @@
@click="handlePerClick(item)"
>
<img :src="item.imageUrl" alt />
<div class="person-info">
<el-tooltip
effect="dark"
:content="item.name"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="name">{{ item.name }}</div>
</el-tooltip>
<el-tooltip
effect="dark"
:content="item.position"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="title1">{{ item.position }}</div>
</el-tooltip>
<el-tooltip
effect="dark"
:content="item.name"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="name">{{ item.name }}</div>
</el-tooltip>
<el-tooltip
effect="dark"
:content="item.position"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="title1">{{ item.position }}</div>
</el-tooltip>
</div>
</div>
</div>
......@@ -916,10 +916,10 @@ onMounted(() => {
flex-shrink: 0;
}
.person-info {
width: calc(100% - 48px - 8px);
width: calc(100% - 48px - 8px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap; /* 防止文本换行 */
white-space: nowrap; /* 防止文本换行 */
.name {
font-size: 16px;
font-weight: 700;
......
......@@ -2,128 +2,108 @@
<div class="ask-page">
<div class="left">
<div class="left-title">
<img src="./assets/icon01.png" alt="" />
<img src="./assets/icon01.png" alt />
<div class="tit">新闻资讯</div>
<div class="more" @click="handleToMoreNews">更多 +</div>
</div>
<div class="left-main">
<div v-for="item in leftList.slice(0, 5)" :key="item.id" class="main-item" @click="handleToNewsDetail(item)">
<img :src="item.image || defaultNews" alt="" @error="e => (e.target.src = defaultNews)" />
<div v-for="item in leftList" :key="item.newsId" class="main-item">
<img :src="item.newsImage" alt />
<div class="item-content">
<div class="title">
<CommonPrompt :content="item.title">
{{ item.title }}
</CommonPrompt>
</div>
<div class="content">
<CommonPrompt :content="item.content">
{{ item.content }}
</CommonPrompt>
</div>
<div class="time">{{ item.time }}</div>
<div class="title">{{item.newsTitle}}</div>
<el-tooltip
effect="dark"
:content="item.newsContent"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<div class="content">{{item.newsContent}}</div>
</el-tooltip>
<div class="time">{{item.newsDate}}</div>
</div>
</div>
</div>
</div>
<div class="right">
<div class="right-title">
<img src="./assets/icon02.png" alt="" />
<img src="./assets/icon02.png" alt />
<div class="tit">社交媒体</div>
</div>
<div class="right-main">
<div
v-for="(item, index) in rightList.slice(0, 3)"
:key="item.id"
class="social-item"
@click="handleToSocialDetail(item)"
>
<img :src="item.image || defaultAvatar" alt="" @error="e => (e.target.src = defaultAvatar)" />
<div class="social-item-main" :style="{ backgroundImage: `url(${socialConfig[index].bg})` }">
<div class="cl1">{{ item.name }}</div>
<div class="cl2">{{ item.content }}</div>
<div class="cl3">{{ item.time }}</div>
<div class="trump" v-for="item in rightList">
<img :src="item.personImage" alt />
<div class="trump-main">
<div class="cl1">{{ item.personName }}</div>
<div class="cl2">{{ item.remarks }}</div>
<div class="cl3">{{ item.time }}&nbsp; 发布于{{ item.orgName }}</div>
</div>
</div>
<!-- <div class="mask">
<img src="./assets/title02.png" alt />
<div class="mask-main">
<div class="cl1">{{ rightList[1].name }}</div>
<div class="cl2">{{ rightList[1].content }}</div>
<div class="cl3">{{ rightList[1].time }}</div>
</div>
</div>
<div class="malaby">
<img src="./assets/title03.png" alt />
<div class="malaby-main">
<div class="cl1">{{ rightList[2].name }}</div>
<div class="cl2">{{ rightList[2].content }}</div>
<div class="cl3">{{ rightList[2].time }}</div>
</div>
</div> -->
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import router from "@/router";
import { getRuleRestrictionNews, getRuleRestrictionSocialMedia } from "@/api/ruleRestriction/ruleRestriction";
import CommonPrompt from "../../commonPrompt/index.vue";
import { ref, onBeforeMount } from "vue";
import router from "@/router"
import image01 from './assets/image01.png'
import image02 from './assets/image02.png'
import image03 from './assets/image03.png'
import image04 from './assets/image04.png'
import image05 from './assets/image05.png'
import defaultNews from "../../assets/images/default-icon-news.png";
import defaultAvatar from "../../assets/images/default-icon1.png";
import title01 from "./assets/title01.png";
import title02 from "./assets/title02.png";
import title03 from "./assets/title03.png";
import title01bg from "./assets/title01bg.png";
import title02bg from "./assets/title02bg.png";
import title03bg from "./assets/title03bg.png";
import title01 from './assets/title01.png'
import title02 from './assets/title02.png'
import title03 from './assets/title03.png'
import { getNews, getRemarks } from '@/api/ruleRestriction/index.js'
const leftList = ref([]);
const rightList = ref([]);
const socialConfig = [
{ icon: title01, bg: title01bg },
{ icon: title02, bg: title02bg },
{ icon: title03, bg: title03bg }
];
// 规则限制-查询新闻资讯接口
const getRuleRestrictionNewsData = async () => {
try {
const res = await getRuleRestrictionNews({ moduleId: "0108" });
if (res && res.code === 200) {
leftList.value = (res.data || []).map(item => ({
id: item.newsId,
title: item.newsTitle,
content: item.newsContent,
time: `${item.newsDate}${item.newsOrg ? " · " + item.newsOrg : ""}`,
image: item.newsImage
}));
}
} catch (error) {
console.error("获取规则限制新闻资讯数据失败:", error);
}
};
const getNewsList = async () => {
try {
const res = await getNews('0108');
// console.log('----res', res)
if (res && res.code === 200) {
// console.log('----getNewsList', res.data)
leftList.value = res.data
}
} catch (error) {
console.error("获取新闻资讯接口失败:", error);
}
}
// 规则限制-查询社交媒体接口
const getRuleRestrictionSocialData = async () => {
try {
const res = await getRuleRestrictionSocialMedia({ moduleId: "0108" });
if (res && res.code === 200) {
rightList.value = (res.data || []).map(item => {
const date = new Date(item.time);
const y = date.getFullYear();
const m = (date.getMonth() + 1).toString().padStart(2, "0");
const d = date.getDate().toString().padStart(2, "0");
const hh = date.getHours().toString().padStart(2, "0");
const mm = date.getMinutes().toString().padStart(2, "0");
const formattedTime = `${y}-${m}-${d} ${hh}:${mm} · 发布于${item.orgName}`;
return {
id: item.personId,
name: item.personName,
content: item.remarks,
time: formattedTime,
image: item.personImage
};
});
}
} catch (error) {
console.error("获取规则限制社交媒体数据失败:", error);
}
};
const getRemarksList = async () => {
try {
const res = await getRemarks('0108');
// console.log('----res', res)
if (res && res.code === 200) {
// console.log('----getRemarksList', res.data)
rightList.value = res.data
}
} catch (error) {
console.error("获取社交媒体接口失败:", error);
}
}
// 查看更多新闻资讯
const handleToMoreNews = () => {
const route = router.resolve("/newsBrief");
window.open(route.href, "_blank");
};
// 查看新闻资讯详情
const handleToNewsDetail = item => {
const route = router.resolve({
......@@ -146,10 +126,12 @@ const handleToSocialDetail = item => {
window.open(route.href, "_blank");
};
onMounted(() => {
getRuleRestrictionNewsData();
getRuleRestrictionSocialData();
});
onBeforeMount(async () => {
await getNewsList()
await getRemarksList()
})
</script>
<style scoped lang="scss">
......@@ -211,6 +193,8 @@ onMounted(() => {
width: 792px;
height: 402px;
padding: 20px 22px 21px 21px;
overflow-y: auto;
overflow-x: hidden;
.main-item {
width: 749px;
height: 64px;
......@@ -231,28 +215,23 @@ onMounted(() => {
height: 50px;
position: relative;
.title {
width: 480px;
font-size: 16px;
font-weight: 700;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(59, 65, 75);
cursor: pointer;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.content {
width: 100%;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(59, 65, 75);
cursor: pointer;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
white-space: nowrap; /* 防止文本换行 */
overflow: hidden; /* 隐藏溢出的内容 */
text-overflow: ellipsis; /* 显示省略符号来代表被修剪的文本 */
}
.time {
position: absolute;
......@@ -317,23 +296,112 @@ onMounted(() => {
width: 792px;
height: 402px;
padding: 23px 30px 25px 21px;
overflow: auto;
.social-item {
overflow-y: auto;
overflow-x: hidden;
.trump {
width: 740px;
height: 148px;
margin-bottom: 16px;
display: flex;
cursor: pointer;
img {
width: 36px;
height: 36px;
margin-right: 8.5px;
border-radius: 50%;
}
.social-item-main {
.trump-main {
width: 695.6px;
height: 148px;
background-image: url("./assets/title01bg.png");
padding: 11px 14px 12px 22.5px;
background-size: 100% 100%;
background-repeat: no-repeat;
background-size: cover;
position: relative;
.cl1 {
font-size: 16px;
font-weight: 700;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(59, 65, 75);
margin-bottom: 5px;
}
.cl2 {
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(59, 65, 75);
}
.cl3 {
position: absolute;
top: 11px;
right: 14px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 30px;
color: rgb(95, 101, 108);
}
}
}
.mask {
width: 740px;
height: 76px;
margin-bottom: 16px;
display: flex;
img {
width: 36px;
height: 36px;
margin-right: 8.5px;
}
.mask-main {
width: 695.6px;
height: 76px;
background-image: url("./assets/title02bg.png");
padding: 11px 14px 12px 22.5px;
background-size: cover;
position: relative;
.cl1 {
font-size: 16px;
font-weight: 700;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(59, 65, 75);
margin-bottom: 5px;
}
.cl2 {
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(59, 65, 75);
}
.cl3 {
position: absolute;
top: 11px;
right: 14px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 30px;
color: rgb(95, 101, 108);
}
}
}
.malaby {
width: 740px;
height: 98px;
margin-bottom: 16px;
display: flex;
img {
width: 36px;
height: 36px;
margin-right: 8.5px;
}
.malaby-main {
width: 695.6px;
height: 98px;
background-image: url("./assets/title03bg.png");
padding: 11px 14px 12px 22.5px;
background-size: cover;
position: relative;
.cl1 {
font-size: 16px;
......@@ -366,3 +434,23 @@ onMounted(() => {
}
}
</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;
max-width: 1000px;
}
.common-prompt-popper.el-popper .el-popper__arrow::before {
background-color: rgb(59, 65, 75) !important;
border-color: rgb(59, 65, 75) !important;
}
</style>
<template>
<div class="data-new">
<div class="left">
<img src="./assets/leftbtn.png" alt="" class="left-btn" @click="handlePrev" />
<img src="./assets/rightbtn.png" alt="" class="right-btn" @click="handleNext" />
<img src="./assets/leftbtn.png" alt class="left-btn" @click="changeIndex(-1)" />
<img src="./assets/rightbtn.png" alt class="right-btn" @click="changeIndex(1)" />
<div class="left-top">
<img src="./assets/icon01.png" alt="" />
<img src="./assets/icon01.png" alt />
<div class="left-top-title">规则限制动态</div>
<div class="more" @click="handleClickToDetail">查看详情 ></div>
</div>
<el-carousel
ref="carouselRef"
height="412px"
direction="horizontal"
:autoplay="true"
:interval="5000"
arrow="never"
indicator-position="none"
@change="handleCarouselChange"
>
<el-carousel-item v-for="(item, index) in riskSignalList" :key="item.RULEID || index">
<div class="carousel-item-content">
<div class="left-center">
<img :src="item.PUBLISHORGIMGURL || defaultImg" alt="" />
<div class="left-center-main">
<div class="left-center-main-title">
{{ item.RULENAMEZH || "暂无动态" }}
</div>
<div class="left-center-main-ul">
<ul>
<li>
<span class="ul-title">发布机构:</span>
<span class="ul-content">{{ item.PUBLISHORGNAME || "未知" }}</span>
</li>
<li>
<span class="ul-title">发布日期:</span>
<span class="ul-content">{{ item.PUBLISHDATE || "未知" }}</span>
</li>
<li>
<span class="ul-title">涉及领域:</span>
<div class="ul-tags" v-if="item.ruleAreas && item.ruleAreas.length > 0">
<span
v-for="(field, fIndex) in item.ruleAreas"
:key="fIndex"
class="ul-pie"
:class="'cl' + ((fIndex % 4) + 1)"
>
{{ field }}
</span>
</div>
<span v-else class="ul-content">未知</span>
</li>
<li>
<span class="ul-title">限制实体:</span>
<span class="ul-content">
{{
item.ruleEntities && item.ruleEntities.length > 0
? item.ruleEntities.map(e => e.ORGNAME).join("、")
: "未知"
}}
</span>
</li>
</ul>
</div>
</div>
</div>
<div class="left-bottom">
<ul>
<li class="left-bottom-li">内容摘要:</li>
</ul>
<div class="left-bottom-content">
{{ item.RULEINTRODUCTION || "暂无内容摘要" }}
</div>
</div>
</div>
</el-carousel-item>
<!-- 无数据时的占位展示 -->
<el-carousel-item v-if="riskSignalList.length === 0">
<div class="carousel-item-content">
<div class="left-center">
<img :src="defaultImg" alt="" />
<div class="left-center-main">
<div class="left-center-main-title">暂无规则限制动态</div>
<div class="left-center-main-ul">
<ul>
<li><span class="ul-title">发布机构:</span><span class="ul-content">未知</span></li>
<li><span class="ul-title">发布日期:</span><span class="ul-content">未知</span></li>
<li><span class="ul-title">涉及领域:</span><span class="ul-content">未知</span></li>
<li><span class="ul-title">限制实体:</span><span class="ul-content">未知</span></li>
</ul>
</div>
</div>
</div>
<div class="left-center">
<img src="./assets/usImg.png" alt />
<div class="left-center-main">
<div class="left-center-main-title">{{ latestUpdateList[latestUpdateIndex].RULENAMEZH }}</div>
<div class="left-center-main-ul">
<ul>
<li>
<span class="ul-title">发布机构:</span>
<span class="ul-content">{{ latestUpdateList[latestUpdateIndex].PUBLISHORGNAME }}</span>
</li>
<li>
<span class="ul-title">发布日期:</span>
<span class="ul-content">{{ latestUpdateList[latestUpdateIndex].PUBLISHDATE }}</span>
</li>
<li>
<span class="ul-title">涉及领域:</span>
<span
class="ul-pie cl1"
v-for="item in latestUpdateList[latestUpdateIndex].ruleAreas"
>{{ item }}</span>
<!-- <span class="ul-pie cl2">集成电路</span>
<span class="ul-pie cl3">新材料</span>
<span class="ul-pie cl4">生物科技</span>-->
</li>
<li>
<span class="ul-title">限制实体:</span>
<span
class="ul-content"
v-for="item in latestUpdateList[latestUpdateIndex].ruleEntities"
>{{ item.ORGNAME }} &nbsp;</span>
</li>
</ul>
</div>
</el-carousel-item>
</el-carousel>
</div>
<!-- <div class="left-center-title">国会法案</div> -->
</div>
<div class="left-bottom">
<ul>
<li class="left-bottom-li">内容摘要:</li>
</ul>
<div class="left-bottom-content">{{ latestUpdateList[latestUpdateIndex].RULEINTRODUCTION }}</div>
</div>
</div>
<div class="right">
<div class="right-top">
<img src="./assets/icon02.png" alt="" />
<img src="./assets/icon02.png" alt />
<div class="right-top-title">
风险信号
<span>{{ riskSignals.length }}</span>
<span>{{ list.length }}</span>
</div>
</div>
<div style="margin: 6px 34px 0 23px">
<div v-for="item in riskSignals" :key="item.id" class="right-main" @click="handleToRiskDetail(item)">
<div v-for="(item, index) in list" :key="index" class="right-main">
<div
class="main-left"
:class="{ cl4: item.title === '特别重大', cl5: item.title === '重大风险', cl6: item.title === '一般风险' }"
>
{{ item.title }}
</div>
<div class="item-right">
<div class="main-center">
<CommonPrompt :content="item.content">
{{ item.content }}
</CommonPrompt>
</div>
<div class="main-right">{{ item.time }}</div>
</div>
:class="{ cl4: item.signalLevel === '特别重大', cl5: item.signalLevel === '重大风险', cl6: item.signalLevel === '一般风险'}"
>{{ item.signalLevel }}</div>
<div class="main-center">{{ item.signalTitle }}</div>
<div class="main-right">{{ item.signalTime }}</div>
</div>
</div>
<div class="right-mainbtn" @click="handleToMoreRiskSignal">
<img src="./assets/btn.png" alt="" />
<img src="./assets/btn.png" alt />
查看更多
</div>
</div>
......@@ -132,65 +78,94 @@
</template>
<script setup>
import { ref, onMounted, computed } from "vue";
import { ref, onBeforeMount, computed } from "vue";
import router from "@/router";
import { getRuleRestrictionLatest, getRuleRestrictionRiskSignal } from "@/api/ruleRestriction/ruleRestriction";
import defaultImg from "./assets/usImg.png";
import CommonPrompt from "../../commonPrompt/index.vue";
import { getLatestUpdates, getRiskSignal } from '@/api/ruleRestriction/index.js'
// 规则限制-查询风险信号数据
const riskSignals = ref([]);
const getRuleRestrictionRiskSignalData = async () => {
try {
const res = await getRuleRestrictionRiskSignal({ moduleId: "0108" });
if (res && res.code === 200) {
riskSignals.value = (res.data || []).map(item => ({
id: item.signalId,
title: item.signalLevel,
content: item.signalTitle,
time: item.signalTime,
ruleLimitId: item.ruleLimitId
}));
}
} catch (error) {
console.error("获取规则限制风险信号数据失败:", error);
}
};
const list = ref([
{
id: 1,
title: "特别重大",
content: "保护美国资金与专业知识免受敌对研究利用法案",
time: "一天前"
},
{
id: 2,
title: "特别重大",
content: "美国国土安全部终止哈佛大学SEVP认证",
time: "一天前"
},
{
id: 3,
title: "重大风险",
content: "众议院“美中战略竞争特别委员会”向国会提...",
time: "一天前"
},
{
id: 4,
title: "重大风险",
content: '2026财年拨款法案要求重启"中国行动计划"',
time: "一天前"
}
]);
// 最新动态列表
const latestUpdateList = ref([{}])
// 当前显示最新动态的序号
const latestUpdateIndex = ref(0)
// 改变序号
const changeIndex = (num) => {
if (num === -1) {
// 判断当前是否是第一个,是的话则将序号设置为最后一个
if (latestUpdateIndex.value === 0) {
latestUpdateIndex.value = latestUpdateList.value.length - 1
} else {
latestUpdateIndex.value--
}
} else {
// 判断当前是否是最后一个,是的话则将序号设置为第一个
if (latestUpdateIndex.value === latestUpdateList.value.length - 1) {
latestUpdateIndex.value = 0
} else {
latestUpdateIndex.value++
}
}
}
// 规则限制-获取规则限制动态
const riskSignalList = ref([]);
const carouselRef = ref(null);
const activeIndex = ref(0);
const getRuleRestrictionLatestData = async () => {
try {
const res = await getRuleRestrictionLatest();
if (res && res.code === 200) {
riskSignalList.value = res.data || [];
}
} catch (error) {
console.error("获取规则限制动态数据失败:", error);
}
};
const getLatestUpdateInfo = async () => {
try {
const res = await getLatestUpdates();
// console.log('------getLatestUpdateInfo res', res)
if (res && res.code === 200) {
console.log('----getLatestUpdateInfo', res.data)
latestUpdateList.value = res.data
}
} catch (error) {
console.error("获取最新动态接口失败:", error);
}
}
// 轮播图手动切换
const handlePrev = () => {
if (carouselRef.value) {
carouselRef.value.prev();
}
};
const handleNext = () => {
if (carouselRef.value) {
carouselRef.value.next();
}
};
const getRiskSignalInfo = async () => {
try {
const res = await getRiskSignal('0108');
console.log('------getRiskSignalInfo res', res)
if (res && res.code === 200) {
console.log('----getRiskSignalInfo', res.data)
list.value = res.data
}
} catch (error) {
console.error("获取风险信号接口失败:", error);
}
}
// 轮播切换回调
const handleCarouselChange = index => {
activeIndex.value = index;
};
// // 跳转详情
// const handleClickToDetail = () => {
// // router.push("/decreeLayout");
// // const route = router.resolve("");
// window.open(`/ruleRestrictions/detail?id=${latestUpdateList.value[latestUpdateIndex.value].RULEID}`, "_blank");
// };
// 左侧展示的主动态
const mainTrend = computed(() => {
......@@ -198,11 +173,6 @@ const mainTrend = computed(() => {
return riskSignalList.value[activeIndex.value] || riskSignalList.value[0];
});
onMounted(() => {
getRuleRestrictionLatestData();
getRuleRestrictionRiskSignalData();
});
// 点击风险信号详情
const handleToRiskDetail = (item) => {
const curRoute = router.resolve({
......@@ -228,9 +198,14 @@ const handleClickToDetail = item => {
// 查看更多动态
const handleToMoreRiskSignal = () => {
const route = router.resolve("/riskSignal");
window.open(route.href, "_blank");
const route = router.resolve("/riskSignal");
window.open(route.href, "_blank");
};
onBeforeMount(async () => {
await getLatestUpdateInfo()
await getRiskSignalInfo()
})
</script>
<style scoped lang="scss">
......@@ -514,7 +489,7 @@ const handleToMoreRiskSignal = () => {
.right-main {
width: 468px;
padding-right: 5px;
height: 47px;
// height: 47px;
border-radius: 2px;
display: flex;
align-items: center;
......@@ -524,7 +499,7 @@ const handleToMoreRiskSignal = () => {
}
.main-left {
width: 40px;
height: 40px;
// height: 40px;
margin: 4px 13px 3px 2px;
border-radius: 50%;
font-size: 12px;
......@@ -542,40 +517,29 @@ const handleToMoreRiskSignal = () => {
background-color: rgba(255, 247, 230, 1);
color: rgba(250, 140, 22, 1);
}
.cl6 {
background-color: rgba(246, 255, 237, 1);
color: rgba(82, 196, 26, 1);
.cl6 {
background-color: rgba(255, 247, 230, 1);
color: rgb(22, 223, 250);
}
.item-right {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
.main-center {
flex: 1;
height: 30px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 30px;
color: rgb(59, 65, 75);
margin-right: 10px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.main-right {
width: 100px;
height: 24px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(132, 136, 142);
text-align: right;
flex-shrink: 0;
}
.main-center {
width: 347px;
// height: 30px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 30px;
color: rgb(59, 65, 75);
margin-right: 2px;
}
.main-right {
width: 60px;
// height: 24px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(132, 136, 142);
text-align: right;
}
}
.right-mainbtn {
......
......@@ -2,74 +2,71 @@
<div class="datasub">
<div class="left">
<div class="left-title">
<img src="./assets/icon01.png" alt="" />
<img src="./assets/icon01.png" alt />
<div class="tit">各类型合作限制政策对比</div>
<el-select v-model="value1" placeholder="Select" class="select">
<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<div class="left-main">
<div class="left-main-echarts" ref="leftChartRef"></div>
</div>
<div class="left-main">
<div class="left-main-echarts" ref="leftChartRef"></div>
</div>
</div>
<div class="right">
<div class="right-title">
<img src="./assets/icon02.png" alt="" />
<img src="./assets/icon02.png" alt />
<div class="tit">各领域规则分布情况</div>
<el-select v-model="value2" placeholder="Select" class="select1">
<el-select v-model="value2" placeholder="Select" class="select1">
<el-option v-for="item in options2" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="value" placeholder="Select" class="select">
<el-select v-model="value" placeholder="Select" class="select">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<div class="right-main">
<div class="right-main-echarts" ref="rightChartRef"></div>
</div>
<div class="right-main">
<div class="right-main-echarts" ref="rightChartRef"></div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
import * as echarts from "echarts";
import { getAreaDistribution, getEntityChangeTrend } from '@/api/ruleRestriction/index.js'
const value = ref("近十年");
const value1 = ref("2025");
const value2 = ref("全部限制手段");
const value = ref(10);
const value1 = ref("2025");
const value2 = ref("01");
const options = [
{
value: "近十年",
label: "近十年"
},
{
value: "近五年",
label: "近五年"
}
{
value: 10,
label: "近十年"
},
{
value: 5,
label: "近五年"
}
];
const options1 = [
{
value: "2025年",
label: "2025年"
},
{
value: "2024年",
label: "2024年"
}
{
value: "2025",
label: "2025年"
},
{
value: "2024",
label: "2024年"
}
];
const options2 = [
{
value: "全部限制手段",
label: "全部限制手段"
},
{
value: "人工智能",
label: "人工智能"
},
{
value: "集成电路",
label: "集成电路"
}
{
value: "01",
label: "行政令"
},
{
value: "02",
label: "法案"
}
];
const leftChartRef = ref(null);
......@@ -77,268 +74,330 @@ const rightChartRef = ref(null);
let leftChart;
let rightChart;
const initLeftDonut = () => {
if (!leftChartRef.value) return;
if (leftChart) leftChart.dispose();
leftChart = echarts.init(leftChartRef.value);
const data = [
{ name: "集成电路", value: 50 },
{ name: "人工智能", value: 46 },
{ name: "通信网络", value: 40 },
{ name: "能源", value: 32 },
{ name: "先进制造", value: 31 },
{ name: "生物科技", value: 31 },
{ name: "航空航天", value: 30 },
{ name: "新材料", value: 24 }
];
const colors = [
"rgba(105, 177, 255, 1)", // 集成电路
"rgba(255, 192, 105, 1)", // 人工智能
"rgba(135, 232, 222, 1)", // 通信网络
"rgba(89, 126, 247, 1)", // 能源
"rgba(214, 228, 255, 1)", // 先进制造
"rgba(255, 120, 117, 1)", // 生物科技
"rgba(179, 127, 235, 1)", // 航空航天
"rgba(255, 163, 158, 1)" // 新材料
];
const option = {
color: colors,
tooltip: { trigger: "item", formatter: ({ name, value, percent }) => `${name}<br/>${value}${percent}%` },
series: [{
type: "pie",
radius: [96, 120],
center: ["50%", "50%"],
avoidLabelOverlap: true,
itemStyle: { borderWidth: 0 },
label: {
show: true,
position: "outside",
alignTo: 'edge',
formatter: ({ name, value, percent }) => `{name|${name}} {value|${value}项} {percent|${percent}%}`,
minMargin: 5,
edgeDistance: 10,
lineHeight: 15,
rich: {
name: { fontSize: 16, fontFamily: "Microsoft YaHei", fontWeight: 700, lineHeight: 24, color: "rgb(59, 65, 75)" },
value: { fontSize: 14, fontFamily: "Microsoft YaHei", fontWeight: 400, lineHeight: 22, color: "rgb(95, 101, 108)" },
percent: { fontSize: 14, fontFamily: "Microsoft YaHei", fontWeight: 400, lineHeight: 22, color: "rgb(95, 101, 108)" }
}
},
labelLine: {
show: true,
length: 30,
length2: 0,
maxSurfaceAngle: 80
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < leftChart.getWidth() / 2;
const points = params.labelLinePoints;
// 导航线终点在标签下方
const lineY = params.labelRect.y + params.labelRect.height;
points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width;
points[2][1] = lineY;
points[1][1] = lineY;
return {
labelLinePoints: points
};
},
data: data.map((d, i) => ({
...d,
labelLine: { lineStyle: { color: colors[i], width: 1 } }
}))
}]
};
leftChart.setOption(option);
const colors = [
{
name: '集成电路',
value: "rgba(105, 177, 255, 1)",
},
{
name: '新一代通信网络',
value: "rgba(135, 232, 222, 1)",
},
{
name: '人工智能',
value: "rgba(255, 192, 105, 1)",
},
{
name: '能源',
value: "rgba(89, 126, 247, 1)",
},
{
name: '先进制造',
value: "rgba(214, 228, 255, 1)",
},
{
name: '生物科技',
value: "rgba(255, 120, 117, 1)",
},
{
name: '航空航天',
value: "rgba(179, 127, 235, 1)",
},
{
name: '新材料',
value: "rgba(255, 163, 158, 1)",
}
];
const initLeftDonut = async () => {
if (!leftChartRef.value) return;
if (leftChart) leftChart.dispose();
leftChart = echarts.init(leftChartRef.value);
let data = []
try {
const params = {
year: value1.value
}
const res = await getAreaDistribution(params);
if (res && res.code === 200) {
console.log('----getAreaDistribution', res.data)
for (let i = 0; i < res.data.length; i++) {
let item = {
name: '',
value: 0
}
item.name = res.data[i].AREANAME
item.value = res.data[i].AREACOUNT
item.itemStyle = {
color: getColor(colors, item.name)
}
data.push(item)
}
}
} catch (error) {
console.error("获取限制领域分布情况接口失败:", error);
}
// console.log('----data', data)
// const data = [
// { name: "集成电路", value: 50 },
// { name: "人工智能", value: 46 },
// { name: "通信网络", value: 40 },
// { name: "能源", value: 32 },
// { name: "先进制造", value: 31 },
// { name: "生物科技", value: 31 },
// { name: "航空航天", value: 30 },
// { name: "新材料", value: 24 }
// ];
const option = {
tooltip: { trigger: "item", formatter: ({ name, value, percent }) => `${name}<br/>${value}${percent}%` },
series: [{
type: "pie",
radius: [96, 120],
center: ["50%", "50%"],
avoidLabelOverlap: true,
itemStyle: { borderWidth: 0 },
label: {
show: true,
position: "outside",
alignTo: 'edge',
formatter: ({ name, value, percent }) => `{name|${name}} {value|${value}项} {percent|${percent}%}`,
minMargin: 5,
edgeDistance: 10,
lineHeight: 15,
rich: {
name: { fontSize: 16, fontFamily: "Microsoft YaHei", fontWeight: 700, lineHeight: 24, color: "rgb(59, 65, 75)" },
value: { fontSize: 14, fontFamily: "Microsoft YaHei", fontWeight: 400, lineHeight: 22, color: "rgb(95, 101, 108)" },
percent: { fontSize: 14, fontFamily: "Microsoft YaHei", fontWeight: 400, lineHeight: 22, color: "rgb(95, 101, 108)" }
}
},
labelLine: {
show: true,
length: 30,
length2: 0,
maxSurfaceAngle: 80
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < leftChart.getWidth() / 2;
const points = params.labelLinePoints;
// 导航线终点在标签下方
const lineY = params.labelRect.y + params.labelRect.height;
points[2][0] = isLeft ? params.labelRect.x : params.labelRect.x + params.labelRect.width;
points[2][1] = lineY;
points[1][1] = lineY;
return {
labelLinePoints: points
};
},
data: data.map((d, i) => ({
...d,
labelLine: { lineStyle: { color: getColor(colors, d.name), width: 1 } }
}))
}]
};
leftChart.setOption(option);
};
const initRightLine = () => {
if (!rightChartRef.value) return;
if (rightChart) rightChart.dispose();
rightChart = echarts.init(rightChartRef.value);
const years = ['2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022', '2023', '2024', '2025'];
const seriesData = [
{ name: '人工智能', color: 'rgb(5, 95, 194)', data: [150, 90, 65, 95, 75, 95, 130, 150, 140, 170, 175, 185] },
{ name: '集成电路', color: 'rgba(19, 168, 168, 1)', data: [65, 95, 125, 115, 135, 145, 165, 165, 165, 175, 180, 175] },
{ name: '量子科技', color: 'rgba(114, 46, 209, 1)', data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 12] },
{ name: '生物科技', color: 'rgba(250, 140, 22, 1)', data: [12, 8, 8, 12, 12, 15, 20, 30, 25, 30, 42, 42] },
{ name: '通信网络', color: 'rgba(105, 177, 255, 1)', data: [42, 38, 45, 52, 52, 48, 52, 72, 65, 62, 65, 58] },
{ name: '能源', color: 'rgb(206, 79, 81)', data: [98, 75, 62, 82, 62, 72, 82, 122, 118, 148, 138, 105] }
];
const option = {
color: seriesData.map(s => s.color),
legend: {
top: 10,
left: 'center',
itemWidth: 12,
itemHeight: 12,
itemGap: 20,
icon: 'circle',
textStyle: {
fontSize: 16,
fontWeight: 400,
lineHeight: 24,
fontFamily: 'Microsoft YaHei',
color: 'rgb(95, 101, 108)'
}
},
grid: {
top: 60,
left: 50,
right: 40,
bottom: 40
},
xAxis: {
type: 'category',
data: years,
boundaryGap: false,
axisLine: {
lineStyle: { color: '#E5E7EB' }
},
axisLabel: {
color: 'rgba(132, 136, 142, 1)',
fontSize: 14,
fontWeight: 400,
lineHeight: 22,
fontFamily: 'Microsoft YaHei'
}
},
yAxis: {
type: 'value',
min: 0,
max: 200,
interval: 40,
axisLine: { show: false },
axisTick: { show: false },
axisLabel: {
color: 'rgba(132, 136, 142, 1)',
fontSize: 14,
fontWeight: 400,
lineHeight: 22,
fontFamily: 'Microsoft YaHei'
},
splitLine: {
lineStyle: { color: '#E5E7EB' }
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line'
}
},
series: [
{
name: '人工智能',
type: 'line',
data: seriesData[0].data,
smooth: false,
symbol: 'circle',
symbolSize: 6,
lineStyle: { width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(5, 95, 194, 0.25)' },
{ offset: 1, color: 'rgba(5, 95, 194, 0.05)' }
])
}
},
{
name: '集成电路',
type: 'line',
data: seriesData[1].data,
smooth: false,
symbol: 'circle',
symbolSize: 6,
lineStyle: { width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(19, 168, 168, 0.25)' },
{ offset: 1, color: 'rgba(19, 168, 168, 0.05)' }
])
}
},
{
name: '量子科技',
type: 'line',
data: seriesData[2].data,
smooth: false,
symbol: 'circle',
symbolSize: 6,
lineStyle: { width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(114, 46, 209, 0.25)' },
{ offset: 1, color: 'rgba(114, 46, 209, 0.05)' }
])
}
},
{
name: '生物科技',
type: 'line',
data: seriesData[3].data,
smooth: false,
symbol: 'circle',
symbolSize: 6,
lineStyle: { width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(250, 140, 22, 0.25)' },
{ offset: 1, color: 'rgba(250, 140, 22, 0.05)' }
])
}
},
{
name: '通信网络',
type: 'line',
data: seriesData[4].data,
smooth: false,
symbol: 'circle',
symbolSize: 6,
lineStyle: { width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(105, 177, 255, 0.25)' },
{ offset: 1, color: 'rgba(105, 177, 255, 0.05)' }
])
}
const initRightLine = async () => {
if (!rightChartRef.value) return;
if (rightChart) rightChart.dispose();
rightChart = echarts.init(rightChartRef.value);
// 首先根据现在的年份,然后再根据所选的年限生成years
const currentYear = new Date().getFullYear()
// 再根据年限往前倒退
const years = []
for (let i = value.value - 1; i >= 0; i--) {
const year = currentYear - i + ''
years.push(year)
}
console.log('----years', years)
// 根据后端生成的数据然后填充数据
const seriesData = []
let maxValue = 0
try {
const params = {
year: value.value,
type: value2.value
}
const res = await getEntityChangeTrend(params);
console.log('-----getEntityChangeTrendList res', res)
if (res && res.code === 200) {
console.log('----getEntityChangeTrendList', res.data)
// 对查询到的数据进行分类
for (let i = 0; i < res.data.length; i++) {
const item = res.data[i]
maxValue = Math.max(item.ENTITYCOUNT, maxValue)
// 优先遍历seriesData中是否已经存在name对象
const index = seriesData.findIndex((ele) => ele.name === item.AREANAME)
// console.log('---seriesData', i, JSON.stringify(seriesData), index)
if (index !== -1) {
const yearIndex = years.findIndex((y) => y === item.YEAR)
seriesData[index].data[yearIndex] = item.ENTITYCOUNT
} else {
const data = new Array(value.value).fill(0)
const yearIndex = years.findIndex((y) => y === item.YEAR)
data[yearIndex] = item.ENTITYCOUNT
// 新建
const color_ = getColor(colors, item.AREANAME)
// 以逗号划分为数组并修改最后一部分的值
const colorArray = color_.split(',')
const colorArray1 = JSON.parse(JSON.stringify(colorArray))
const colorArray2 = JSON.parse(JSON.stringify(colorArray))
colorArray1[colorArray1.length - 1] = '0.5)'
colorArray2[colorArray2.length - 1] = '0.1)'
const color1 = colorArray1.join(',')
const color2 = colorArray2.join(',')
console.log(item.AREANAME, '----color1 color2', color1, color2)
const options = {
name: item.AREANAME,
type: 'line',
data: data,
smooth: false,
symbol: 'circle',
symbolSize: 6,
lineStyle: { width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: color1 },
{ offset: 1, color: color2 }
])
},
{
name: '能源',
type: 'line',
data: seriesData[5].data,
smooth: false,
symbol: 'circle',
symbolSize: 6,
lineStyle: { width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(206, 79, 81, 0.25)' },
{ offset: 1, color: 'rgba(206, 79, 81, 0.05)' }
])
}
itemStyle: {
color: color_
}
]
};
rightChart.setOption(option);
}
seriesData.push(options)
}
}
}
} catch (error) {
console.error("获取受限实体数量变化趋势接口失败:", error);
}
const option = {
color: colors.map((item) => {
return item.value
}),
legend: {
top: 10,
left: 'center',
itemWidth: 12,
itemHeight: 12,
itemGap: 20,
icon: 'circle',
textStyle: {
fontSize: 16,
fontWeight: 400,
lineHeight: 24,
fontFamily: 'Microsoft YaHei',
color: 'rgb(95, 101, 108)'
}
},
grid: {
top: 60,
left: 50,
right: 40,
bottom: 40
},
xAxis: {
type: 'category',
data: years,
boundaryGap: false,
axisLine: {
lineStyle: { color: '#E5E7EB' }
},
axisLabel: {
color: 'rgba(132, 136, 142, 1)',
fontSize: 14,
fontWeight: 400,
lineHeight: 22,
fontFamily: 'Microsoft YaHei'
}
},
yAxis: {
type: 'value',
min: 0,
max: maxValue * 1.5,
interval: maxValue * 0.5,
axisLine: { show: false },
axisTick: { show: false },
axisLabel: {
color: 'rgba(132, 136, 142, 1)',
fontSize: 14,
fontWeight: 400,
lineHeight: 22,
fontFamily: 'Microsoft YaHei'
},
splitLine: {
lineStyle: { color: '#E5E7EB' }
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line'
}
},
series: seriesData
};
rightChart.setOption(option);
};
const handleResize = () => {
if (leftChart) leftChart.resize();
if (rightChart) rightChart.resize();
const getColor = (colors, name) => {
const index = colors.findIndex((i) => i.name === name)
if (index !== -1) {
return colors[index].value
} else {
return "rgba(105, 177, 255, 1)"
}
}
const handleResize = () => {
if (leftChart) leftChart.resize();
if (rightChart) rightChart.resize();
};
onMounted(() => {
initLeftDonut();
initRightLine();
window.addEventListener("resize", handleResize);
const getEntityChangeTrendList = async () => {
try {
const params = {
year: value.value,
type: value2.value
}
const res = await getEntityChangeTrend(params);
console.log('-----getEntityChangeTrendList res', res)
if (res && res.code === 200) {
console.log('----getEntityChangeTrendList', res.data)
}
} catch (error) {
console.error("获取受限实体数量变化趋势接口失败:", error);
}
}
watch(value1, () => {
initLeftDonut()
})
watch([value, value2], () => {
initRightLine()
})
onMounted(async () => {
await initLeftDonut();
await initRightLine();
window.addEventListener("resize", handleResize);
});
onBeforeUnmount(() => {
window.removeEventListener("resize", handleResize);
if (leftChart) { leftChart.dispose(); leftChart = null; }
if (rightChart) { rightChart.dispose(); rightChart = null; }
onBeforeUnmount(() => {
window.removeEventListener("resize", handleResize);
if (leftChart) { leftChart.dispose(); leftChart = null; }
if (rightChart) { rightChart.dispose(); rightChart = null; }
});
</script>
......@@ -382,24 +441,24 @@ onBeforeUnmount(() => {
line-height: 26px;
color: rgb(5, 95, 194);
}
.select {
width: 120px;
height: 28px;
padding: 0px 12px;
position: absolute;
top: 11px;
right: 31px;
}
.select {
width: 120px;
height: 28px;
padding: 0px 12px;
position: absolute;
top: 11px;
right: 31px;
}
}
.left-main {
width: 792px;
height: 412px;
padding: 52px 60px 78px 61px;
.left-main-echarts {
width: 100%;
height: 100%;
}
}
.left-main {
width: 792px;
height: 412px;
padding: 52px 60px 78px 61px;
.left-main-echarts {
width: 100%;
height: 100%;
}
}
}
.right {
width: 792px;
......@@ -408,11 +467,11 @@ onBeforeUnmount(() => {
// border: 1px solid rgb(234, 236, 238);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background-color: #fff;
.right-title {
width: 792px;
height: 48px;
border-bottom: 1px solid rgb(234, 236, 238);
position: relative;
.right-title {
width: 792px;
height: 48px;
border-bottom: 1px solid rgb(234, 236, 238);
position: relative;
img {
width: 19px;
height: 19px;
......@@ -420,42 +479,42 @@ onBeforeUnmount(() => {
top: 16px;
left: 21px;
}
.tit {
margin-left: 60px;
height: 48px;
padding: 11px 0;
font-size: 20px;
font-weight: 700;
font-family: "Microsoft YaHei";
line-height: 26px;
color: rgb(5, 95, 194);
}
.select1 {
width: 155px;
height: 28px;
padding: 0px 12px;
position: absolute;
top: 11px;
right: 163px;
}
.select {
width: 120px;
height: 28px;
padding: 0px 12px;
position: absolute;
top: 11px;
right: 31px;
}
.tit {
margin-left: 60px;
height: 48px;
padding: 11px 0;
font-size: 20px;
font-weight: 700;
font-family: "Microsoft YaHei";
line-height: 26px;
color: rgb(5, 95, 194);
}
.select1 {
width: 155px;
height: 28px;
padding: 0px 12px;
position: absolute;
top: 11px;
right: 163px;
}
.select {
width: 120px;
height: 28px;
padding: 0px 12px;
position: absolute;
top: 11px;
right: 31px;
}
}
.right-main {
width: 792px;
height: 421px;
padding: 15px 37px 25px 46px;
.right-main-echarts {
width: 100%;
height: 100%;
}
}
.right-main {
width: 792px;
height: 421px;
padding: 15px 37px 25px 46px;
.right-main-echarts {
width: 100%;
height: 100%;
}
}
}
}
</style>
......@@ -7,9 +7,7 @@
class="nav-item"
:class="{ active: item === activeItem }"
@click="handleClickNav(item)"
>
{{ item }}
</div>
>{{ item }}</div>
</div>
<el-select v-model="value" placeholder="Select" class="select">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
......@@ -20,49 +18,55 @@
<div class="left-ti2"></div>
<div class="left-title">发布时间</div>
<div class="left-content">
<div v-for="(item, i) in dataList" :key="item.id" class="left-item">
<input type="checkbox" :checked="i === 0" />{{ item.name }}
</div>
<el-checkbox
v-for="(item, index) in dataList"
:key="index"
v-model="item.checked"
:label="item.label"
@change="handleFilterChange(item, dataList)"
/>
</div>
<div class="left-title cl1">涉及领域</div>
<div class="left-content">
<div v-for="(item, i) in dataList2" :key="item.id" class="left-item">
<input type="checkbox" :checked="i === 0" />{{ item.name }}
</div>
<el-checkbox
v-for="(item, index) in techFields"
:key="index"
v-model="item.checked"
:label="item.label"
@change="handleFilterChange(item, techFields)"
/>
</div>
</div>
<div class="right">
<div class="right-title">
<img src="./assets/icon01.png" alt="" />
<img src="./assets/icon01.png" alt />
<div>规则限制历程</div>
</div>
<div class="right-main">
<div class="main-content">
<div v-for="item in mainDataList" :key="item.id" class="main-item">
<div class="date">{{ item.date }}</div>
<img :src="item.img" alt="" class="img" />
<div class="date">{{ getDate(item) }}</div>
<img :src="item.ORGPICTURE" alt class="img" />
<div class="box">
<div class="title" @click="handleClick(item)">{{ item.title }}</div>
<div class="content" @click="handleClick(item)">{{ item.content }}</div>
<div class="title">{{ item.RULENAME }}</div>
<div class="content">{{ item.RULEINTRODUCTION }}</div>
<div class="domain">
<div v-for="(domain, i) in item.domain" :key="i" class="domain-item">{{ domain }}</div>
<div v-for="(domain, i) in item.ruleAreas" :key="i" class="domain-item">{{ domain }}</div>
</div>
<div
class="type"
:class="{
type1: item.type === '行政令',
type2: item.type === '法案',
type3: item.type === '301调查'
type1: item.RULEMEANS === '行政令',
type2: item.RULEMEANS === '法案',
type3: item.RULEMEANS === '301调查'
}"
>
{{ item.type }}
</div>
>{{ item.RULEMEANS }}</div>
</div>
</div>
</div>
<div class="line"></div>
<div class="page">
<div class="count"> {{ total }}</div>
<div class="count">{{ total }}项调查</div>
<el-pagination
v-model:current-page="currentPage"
:page-size="pageSize"
......@@ -82,53 +86,68 @@
<div class="left-ti3"></div>
<div class="left-title">发布时间</div>
<div class="left-content">
<div v-for="(item, i) in dataList" :key="item.id" class="left-item">
<input type="checkbox" :checked="i === 0" />{{ item.name }}
</div>
<el-checkbox
v-for="(item, index) in dataList"
:key="index"
v-model="item.checked"
:label="item.label"
@change="handleFilterChange(item, dataList)"
/>
</div>
<div class="left-title cl1">涉及领域</div>
<div class="left-content">
<div v-for="(item, i) in dataList2" :key="item.id" class="left-item">
<input type="checkbox" :checked="i === 0" />{{ item.name }}
</div>
<el-checkbox
v-for="(item, index) in techFields"
:key="index"
v-model="item.checked"
:label="item.label"
@change="handleFilterChange(item, techFields)"
/>
</div>
<div class="left-title cl2">涉及国家</div>
<div class="left-content">
<div v-for="(item, i) in dataList3" :key="item.id" class="left-item">
<input type="checkbox" :checked="i === 0" />{{ item.name }}
</div>
<el-checkbox
v-for="(item, index) in dataList3"
:key="index"
v-model="item.checked"
:label="item.label"
@change="handleFilterChange(item, dataList3)"
/>
</div>
</div>
<div class="right-unshow">
<div class="top">
<div v-for="item in unionDataList" :key="item.id" class="top-item">
<div class="title">
<img :src="item.img" alt="" />
<div>
<span class="name">{{ item.name }}</span
><span class="abb">{{ item.abb }}</span>
<div class="compose">{{ item.compose }}</div>
<div class="img-list">
<img class="img-style" :src="ele.COUNTRYIMAGE" v-for="ele in item.countries" alt />
</div>
<div
class="type"
:class="{
type1: item.type === '通信网络',
type2: item.type === '集成电路',
type3: item.type === ''
}"
>
{{ item.type }}
<div style="width: calc(100% - 60px)">
<div style="display: flex; justify-content: space-between;">
<div>
<span class="name">{{ item.ACTANAME }}</span>
<span class="abb">{{ item.ACTASHORTNAMEEN }}</span>
</div>
<div class="type">
<div
v-for="(ele, index) in item.area"
:key="index"
:class="{ type1: ele !== '', type3: ele === '' }"
>{{ ele }}</div>
</div>
</div>
<div class="compose">{{ getCompose(item) }}</div>
</div>
</div>
<div class="content">{{ item.content }}</div>
<div class="content">{{ item.ACTAINTRODUCTION }}</div>
</div>
</div>
<div class="bottom">
<div class="count"> {{ total }}</div>
<div class="count">{{ unionDataList.length }}项调查</div>
<el-pagination
v-model:current-page="currentPage"
:page-size="pageSize"
:total="total"
v-model:current-page="currentPageACTA"
:page-size="pageSizeACTA"
:total="totalACTA"
layout="prev, pager, next"
background
@current-change="handlePageChange"
......@@ -140,381 +159,341 @@
</template>
<script setup>
import { ref } from "vue";
import { ref, onMounted, watch } from "vue";
import { useRouter } from "vue-router";
// import whitehouse from "./assets/白宫.png";
// import guohui from "./assets/国会.png";
// import guotuanquanbu from "./assets/国土安全部.png";
// import guowuyuan from "./assets/国务院.png";
// import weishengyanjiuyuan from "./assets/卫生研究院.png";
// import zhongyiyuan from "./assets/众议院.png";
import fda from "./assets/FDA.png";
import swb from "./assets/商务部.png";
import fcc from "./assets/FCC.png";
import flag01 from "./assets/flag01.png";
import flag02 from "./assets/flag02.png";
import flag03 from "./assets/flag03.png";
import flag04 from "./assets/flag04.png";
import flag05 from "./assets/flag05.png";
import flag06 from "./assets/flag06.png";
import flag07 from "./assets/flag07.png";
import flag08 from "./assets/flag08.png";
import flag09 from "./assets/flag09.png";
import flag01 from "./assets/flag01.png"
import flag02 from "./assets/flag02.png"
import flag03 from "./assets/flag03.png"
import flag04 from "./assets/flag04.png"
import flag05 from "./assets/flag05.png"
import flag06 from "./assets/flag06.png"
import flag07 from "./assets/flag07.png"
import flag08 from "./assets/flag08.png"
import flag09 from "./assets/flag09.png"
import { getRuleLimitList, getACTAList, getAcTAAllcountry } from '@/api/ruleRestriction/index.js'
const router = useRouter();
const handleClick = item => {
router.push({
path: "/ruleRestrictions/detail",
query: {
id: item.id
}
});
router.push({
path: "/ruleRestrictions/detail",
query: {
id: item.RULEID
}
});
};
const isShow = ref(true);
const navList = ref(["规则限制政令", "排华科技联盟"]);
const activeItem = ref("规则限制政令");
const handleClickNav = item => {
activeItem.value = item;
if (item === "规则限制政令") {
isShow.value = true;
} else {
isShow.value = false;
}
activeItem.value = item;
if (item === "规则限制政令") {
isShow.value = true;
getRuleLimitListApi()
} else {
isShow.value = false;
getACTAListInfo()
}
};
const value = ref("发布时间");
const value = ref("desc");
const options = [
{
value: "发布时间",
label: "发布时间"
},
{
value: "发布日期",
label: "发布日期"
}
{
value: "asc",
label: "时间正序"
},
{
value: "desc",
label: "时间倒序"
}
];
const dataList = ref([
{
id: 1,
name: "全部时间"
},
{
id: 2,
name: "2025年"
},
{
id: 3,
name: "2024年"
},
{
id: 4,
name: "2023年"
},
{
id: 5,
name: "2022年"
},
{
id: 6,
name: "2021年"
},
{
id: 7,
name: "2020年"
},
{
id: 8,
name: "更早"
}
{ label: "全部时间", value: "all", checked: true },
{ label: "2025年", value: "2025", checked: false },
{ label: "2024年", value: "2024", checked: false },
{ label: "2023年", value: "2023", checked: false },
{ label: "2022年", value: "2022", checked: false },
{ label: "2021年", value: "2021", checked: false }
]);
const dataList2 = ref([
{
id: 1,
name: "全部领域"
},
{
id: 2,
name: "人工智能"
},
{
id: 3,
name: "集成电路"
},
{
id: 4,
name: "通信网络"
},
{
id: 5,
name: "量子科技"
},
{
id: 6,
name: "能源"
},
{
id: 7,
name: "生物科技"
},
{
id: 8,
name: "航空航天"
},
{
id: 9,
name: "海洋"
},
{
id: 10,
name: "先进制造"
}
const techFields = ref([
{ label: "全部领域", value: "all", checked: true },
{ label: "人工智能", value: "1", checked: false },
{ label: "生物科技", value: "2", checked: false },
{ label: "新一代通信网络", value: "3", checked: false },
{ label: "量子科技", value: "4", checked: false },
{ label: "新能源", value: "5", checked: false },
{ label: "集成电路", value: "6", checked: false },
{ label: "海洋", value: "7", checked: false },
{ label: "先进制造", value: "8", checked: false },
{ label: "新材料", value: "9", checked: false },
{ label: "航空航天", value: "10", checked: false },
{ label: "深海", value: "11", checked: false },
{ label: "极地", value: "12", checked: false },
{ label: "太空", value: "13", checked: false },
{ label: "核", value: "14", checked: false },
{ label: "其他", value: "99", checked: false }
]);
const dataList3 = ref([
{
id: 1,
name: "全部国家"
},
{
id: 2,
name: "美国"
},
{
id: 3,
name: "日本"
},
{
id: 4,
name: "韩国"
},
{
id: 5,
name: "英国"
},
{
id: 6,
name: "澳大利亚"
},
{
id: 7,
name: "新西兰"
},
{
id: 8,
name: "加拿大"
},
{
id: 9,
name: "欧盟"
},
{
id: 10,
name: "中国台湾"
}
{
"value": "all",
"label": "全部国家",
checked: true
},
{
"value": "0103",
"label": "韩国",
checked: false
},
{
"value": "0104",
"label": "日本",
checked: false
},
{
"label": "印度",
"value": "0119",
checked: false
},
{
"value": "0203",
"label": "瑞典",
checked: false
},
{
"value": "0204",
"label": "芬兰",
checked: false
},
{
"label": "英国",
"value": "0217",
checked: false
},
{
"value": "0220",
"label": "荷兰",
checked: false
},
{
"value": "0222",
"label": "法国",
checked: false
},
{
"value": "0401",
"label": "澳大利亚",
checked: false
},
{
"value": "0501",
"label": "加拿大",
checked: false
},
{
"value": "0502",
"label": "美国",
checked: false
},
{
"value": "010101",
"label": "中国台湾",
checked: false
}
]);
const mainDataList = ref([
{
id: 1,
title: "美国FDA:针对两家中国第三方检测机构的数据完整性问题采取行动",
content:
"FDA因发现数据伪造或无效问题,向两家中国第三方检测公司(天津中联科技检测有限公司和苏州大学卫生与环境技术研究所)正式发出“一般信函”。",
date: "2025年10月15日",
domain: ["生物科技"],
type: "行政令",
img: fda
},
{
id: 2,
title: "美国商务部:扩大实体清单制裁范围,对中企子公司实施同等管制",
content:
"任何被列入美国出口管制“实体清单”或“军事最终用户清单”的企业,如果其直接或间接持有另一家公司 ​50%或以上的股权,那么这家被控股的公司也将自动受到与清单上母公司同等的出口管制限制",
date: "2025年9月30日",
domain: ["生物科技"],
type: "301调查",
img: swb
},
{
id: 3,
title: "美国商务部:出台全面半导体出口管制",
content: "美国商务部宣称将“至少每年”更新一次管制规则,以堵塞已发现的政策“漏洞”。",
date: "2025年9月15日",
domain: ["生物科技"],
type: "行政令",
img: swb
},
{
id: 4,
title: "美国FCC:出台电信设备市场准入认证新规",
content: "将国家安全审查全面嵌入设备授权程序,对实验室资质、测试标准以及供应链设置严格限制。",
date: "2025年9月8日",
domain: ["生物科技", "通信网络"],
type: "行政令",
img: fcc
},
{
id: 5,
title: "美国FCC:发布“清洁购物车”行动,要求电商平台下架违规中国电子产品",
content:
"在亚马逊、eBay等美国主流电商平台销售的华为、海康威视、中兴、大华等中国品牌的消费电子产品(如家用监控摄像头、智能手表)。",
date: "2025年9月1日",
domain: ["集成电路", "人工智能", "通信网络"],
type: "行政令",
img: fcc
},
{
id: 6,
title: "美国FDA:紧急叫停涉及将美国公民活体细胞送往中国等“敌对国家”实验室的临床试验",
content: "涉及将人类生物样本(如活体细胞)转移至中国进行基因工程等研究的临床试验项目,相关研究被叫停。",
date: "2025年8月26日",
domain: ["生物科技"],
type: "行政令",
img: fda
},
{
id: 7,
title: "美国FDA:更新进口预警措施,对多家中国食品企业产品实施​“自动扣留”​​",
content:
"多家中国食品及农产品出口企业(如广东企业罗非鱼、辽宁企业宠物零食等),被扣留的货物必须在FDA或其认可的实验室内检验合格后方可放行。",
date: "2025年8月22日",
domain: ["生物科技"],
type: "行政令",
img: fda
},
{
id: 8,
title: "美国FCC:禁止使用清单内企业零部件的新设备获得授权,并首次可追溯撤销已获批设备的销售许可",
content: "对“受管制清单”实施技术性补封,建立​“回溯机制”​​ 并封闭​“模块发射器”漏洞。",
date: "2025年8月15日",
domain: ["通信网络"],
type: "行政令",
img: fcc
},
{
id: 9,
title: "美国FDA:针对两家中国第三方检测机构的数据完整性问题采取行动",
content:
"FDA因发现数据伪造或无效问题,向两家中国第三方检测公司(天津中联科技检测有限公司和苏州大学卫生与环境技术研究所)正式发出“一般信函”。",
date: "2025年10月15日",
domain: ["生物科技"],
type: "行政令",
img: fda
},
{
id: 10,
title: "美国商务部:出台全面半导体出口管制",
content: "美国商务部宣称将“至少每年”更新一次管制规则,以堵塞已发现的政策“漏洞”。",
date: "2025年9月15日",
domain: ["生物科技"],
type: "行政令",
img: swb
}
]);
const mainDataList = ref([]);
const unionDataList = ref([
{
id: 1,
name: "AI-RAN联盟",
abb: "QUAD",
compose: "2024年成立 · 美国、英国、日本、韩国、法国、加拿大等10国",
content:
"由英伟达牵头,联合软银、亚马逊云科技、微软、爱立信、诺基亚、三星、T-Mobile等多家行业领导者成立了的人工智能无线接入网络技术联盟。",
type: "通信网络",
img: flag01
},
{
id: 2,
name: "Next G联盟",
abb: "",
compose: "2021年成立 · 美国、瑞典、芬兰、韩国",
content: "在6G技术研发和未来标准制定上抢先布局,旨在主导6G发展方向,其联盟的排他性被解读为针对中国。",
type: "通信网络",
img: flag02
},
{
id: 3,
name: "美日印澳“四边机制”",
abb: "QUAD",
compose: "2021年成立 · 美国、日本、印度、澳大利亚",
content: "在地区安全、基础设施、新兴技术和供应链(特别是半导体)等领域开展排他性合作,筹备构建“印太版北约” 。",
type: "集成电路",
img: flag03
},
{
id: 4,
name: "美国半导体联盟",
abb: "SIAC",
compose: "2021年成立 · 美国、韩国、中国台湾、荷兰",
content:
"初始核心任务是游说美国政府对本土芯片产业提供补贴(如500亿美元的《芯片法案》),但其成员构成未纳入中国大陆企业,具有明显的“排华”倾向。",
type: "集成电路",
img: flag04
},
{
id: 5,
name: "Next G联盟",
abb: "",
compose: "2021年成立 · 美国、瑞典、芬兰、韩国",
content: "在6G技术研发和未来标准制定上抢先布局,旨在主导6G发展方向,其联盟的排他性被解读为针对中国。",
type: "通信网络",
img: flag05
},
{
id: 6,
name: "芯片四方联盟",
abb: "Chip 4",
compose: "2020年成立 · 美国、日本、韩国、中国台湾",
content: "构建将中国大陆排除在外的半导体供应链体系,意图在芯片设计、生产到供应环节形成闭环,限制先进芯片技术对华出口。",
type: "集成电路",
img: flag06
},
{
id: 7,
name: "美英澳三边安全伙伴关系",
abb: "AUKUS",
compose: "2020年成立 · 美国、英国、澳大利亚",
content: "美英两国支持澳大利亚建立核潜艇部队,旨在深化三国在安全和防务能力上的合作。",
type: "",
img: flag07
},
{
id: 8,
name: "印太经济框架",
abb: "IPEF",
compose: "2020年成立 · 美国、英国、澳大利亚",
content: "重点在供应链领域制定新协议,增强透明度与安全性,确保对半导体等关键产品和技术的获取,推动供应链“去中国化”。",
type: "集成电路",
img: flag08
},
{
id: 9,
name: "清洁网络计划",
abb: "",
compose: "2019年成立 · 美国、英国、荷兰",
content:
"在全球5G网络部署和软件应用生态中排除中国的企业和设备,涉及电信运营商、移动应用、应用商店、云服务和海底光缆等多个层面。",
type: "通信网络",
img: flag09
},
{
id: 10,
name: "清洁网络计划",
abb: "",
compose: "2019年成立 · 美国、英国、荷兰",
content:
"在全球5G网络部署和软件应用生态中排除中国的企业和设备,涉及电信运营商、移动应用、应用商店、云服务和海底光缆等多个层面。",
type: "通信网络",
img: flag09
}
]);
const unionDataList = ref([])
// 筛选逻辑处理
const handleFilterChange = (item, list) => {
// 如果点击的是"全部"
if (item.value === 'all') {
if (item.checked) {
// 选中全部,取消其他所有
list.forEach(i => {
if (i.value !== 'all') i.checked = false;
});
} else {
// 取消全部(通常不允许全部取消,至少得选一个,这里如果取消全部,就默认为全部选中)
item.checked = true;
}
} else {
// 点击的是具体项
if (item.checked) {
// 选中具体项,取消"全部"
const allItem = list.find(i => i.value === 'all');
if (allItem) allItem.checked = false;
} else {
// 取消具体项,检查是否还有选中的
const anyChecked = list.some(i => i.checked);
if (!anyChecked) {
const allItem = list.find(i => i.value === 'all');
if (allItem) allItem.checked = true;
}
}
}
// 重置页码并查询
currentPage.value = 0;
if (isShow.value) {
getRuleLimitListApi();
} else {
getACTAListInfo()
}
};
const getRuleLimitListApi = async () => {
// 处理科技领域筛选
let techDomains = [];
const allTech = techFields.value.find(item => item.value === 'all');
if (!allTech || !allTech.checked) {
techDomains = techFields.value
.filter(item => item.checked && item.value !== 'all')
.map(item => item.value);
}
// 处理发布时间时间筛选
let years = [];
const allTime = dataList.value.find(item => item.value === 'all');
if (!allTime || !allTime.checked) {
years = dataList.value
.filter(item => item.checked && item.value !== 'all')
.map(item => item.value);
}
const params = {
areas: techDomains.length > 0 ? techDomains.join(',') : undefined,
years: years.length > 0 ? years.join(',') : undefined,
keywords: undefined,
sortOrder: value.value,
sortField: 'date',
currentPage: currentPage.value,
pageSize: pageSize.value
};
try {
console.log('-----getRuleLimitList params', params)
const res = await getRuleLimitList(params);
console.log('-----getRuleLimitList res', res)
if (res.code === 200) {
console.log('-----getRuleLimitListApi', res.data)
total.value = res.data.numberOfElements
mainDataList.value = res.data.content
}
} catch (error) {
console.error("获取规则限制政令列表查询接口接口失败:", error);
}
}
const getACTAListInfo = async () => {
// 处理科技领域筛选
let techDomains = [];
const allTech = techFields.value.find(item => item.value === 'all');
if (!allTech || !allTech.checked) {
techDomains = techFields.value
.filter(item => item.checked && item.value !== 'all')
.map(item => item.value);
}
// 处理发布时间时间筛选
let years = [];
const allTime = dataList.value.find(item => item.value === 'all');
if (!allTime || !allTime.checked) {
years = dataList.value
.filter(item => item.checked && item.value !== 'all')
.map(item => item.value);
}
// 处理国家筛选
let countries = []
const allCountry = dataList3.value.find(item => item.value === 'all')
if (!allCountry || !allCountry.checked) {
countries = dataList3.value.filter(item => item.checked && item.value !== 'all').map(item => item.value)
}
const params = {
areas: techDomains.length > 0 ? techDomains.join(',') : undefined,
years: years.length > 0 ? years.join(',') : undefined,
keywords: undefined,
countries: countries,
sortOrder: value.value,
sortField: 'date',
currentPage: currentPageACTA.value,
pageSize: pageSizeACTA.value
};
try {
console.log('-----getACTAList params', params)
const res = await getACTAList(params);
console.log('-----getACTAList res', res)
if (res.code === 200) {
console.log('-----getACTAListInfo', res.data)
unionDataList.value = res.data.content
totalACTA.value = res.data.numberOfElements
}
} catch (error) {
console.error("获取规则限制政令列表查询接口接口失败:", error);
}
}
const getCompose = (item) => {
if (item) {
const countries = item.countries.map(i => i.COUNTRYNAME)
return item.ACTAYEAR + '年成立 · ' + countries.join('、')
}
}
watch(value, () => {
if (isShow.value) {
getRuleLimitListApi()
} else {
getACTAListInfo()
}
})
const getDate = (item) => {
if (item && item.PUBLISHDATE) {
let year = item.PUBLISHDATE.split('-')[0]
let month = item.PUBLISHDATE.split('-')[1]
let day = +item.PUBLISHDATE.split('-')[2]
return year + '年' + month + '月' + day + '日'
}
}
onMounted(async () => {
await getRuleLimitListApi()
try {
const res = await getAcTAAllcountry();
console.log('-----getAcTAAllcountry res', res)
if (res.code === 200) {
console.log('-----getAcTAAllcountry', res.data)
}
} catch (error) {
console.error("获取规则限制政令列表查询接口接口失败:", error);
}
})
const total = ref(1205);
const pageSize = ref(121);
const currentPage = ref(5);
const pageSize = ref(10);
const currentPage = ref(0);
const totalACTA = ref(1205);
const pageSizeACTA = ref(10);
const currentPageACTA = ref(0);
const handlePageChange = p => {
currentPage.value = p;
currentPage.value = p;
};
const handlePageChangeACTA = p => {
currentPageACTA.value = p;
};
</script>
......@@ -599,11 +578,23 @@ const handlePageChange = p => {
}
.left-content {
width: 253px;
height: 132px;
// height: 132px;
height: auto;
margin-left: 25px;
margin-top: 13px;
display: flex;
flex-wrap: wrap;
.el-checkbox {
width: 50%;
margin-right: 0;
margin-bottom: 4px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(95, 101, 108);
}
.left-item {
width: 120px;
height: 30px;
......@@ -736,15 +727,15 @@ const handlePageChange = p => {
cursor: pointer;
}
.type {
position: absolute;
top: 0;
right: 0;
padding: 2px 8px;
border-radius: 20px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
position: absolute;
top: 0px;
right: 0px;
}
.type1 {
background-color: rgba(232, 189, 11, 0.1);
......@@ -780,7 +771,7 @@ const handlePageChange = p => {
height: 1150px;
border: 2px solid rgb(235, 238, 242);
position: absolute;
top: 75px;
top: 55px;
left: 120px;
z-index: 1;
}
......@@ -901,7 +892,7 @@ const handlePageChange = p => {
}
.left-content {
width: 253px;
height: 132px;
// height: 132px;
margin-left: 25px;
margin-top: 13px;
display: flex;
......@@ -947,7 +938,7 @@ const handlePageChange = p => {
margin-top: 21px;
}
.cl2 {
margin-top: 58px;
// margin-top: 58px;
}
}
.right-unshow {
......@@ -975,22 +966,19 @@ const handlePageChange = p => {
position: relative;
border-bottom: 1px solid rgb(234, 236, 238);
margin-bottom: 12px;
img {
width: 52px;
height: 52px;
margin-right: 16px;
.img-list {
width: 60px;
height: 46px;
overflow: hidden;
text-align: center;
.img-style {
width: 22px;
height: 22px;
border-radius: 50%;
}
}
.type {
position: absolute;
top: 0;
right: 0;
border-radius: 4px;
border: 1px solid;
padding: 2px 8px;
font-size: 14px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 20px;
display: flex;
}
.name {
font-size: 20px;
......@@ -1020,6 +1008,15 @@ const handlePageChange = p => {
border-color: rgba(145, 202, 255, 1);
color: rgba(22, 119, 255, 1);
background-color: rgba(230, 244, 255, 1);
border-radius: 4px;
border: 1px solid;
padding: 2px 8px;
font-size: 14px;
font-weight: 400;
width: auto;
font-family: "Microsoft YaHei";
line-height: 20px;
margin-right: 4px;
}
.type2 {
border-color: rgba(255, 163, 158, 1);
......@@ -1028,6 +1025,13 @@ const handlePageChange = p => {
}
.type3 {
border: none;
border-radius: 4px;
border: 1px solid;
padding: 2px 8px;
font-size: 14px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 20px;
}
}
.content {
......
......@@ -2,73 +2,92 @@
<div class="cooperation-restrictions-detail">
<div class="nav">
<div class="nav-main">
<img src="./assets/image01.png" alt="" />
<img src="./assets/image01.png" alt />
<div class="content">
<div class="cl1">美国联邦通信委员会(FCC)启动程序撤销对 TUV/宁波的认可</div>
<div class="cl2">FCC Begins Proceedings to Withdraw Recognition of TUV/Ningbo</div>
<div class="cl3">2025年10月24日 10:33 · 美国联邦通信委员会</div>
</div>
<div class="btn">
<button class="btn1"><img src="./assets/icon01.png" alt="" />查看原文</button>
<button class="btn1">
<img src="./assets/icon01.png" alt />查看原文
</button>
<!-- <button class="btn1"><img src="./assets/icon02.png" alt="" />查看官网</button> -->
<button class="btn1 active"><img src="./assets/icon03.png" alt="" />分析报告</button>
<button class="btn1 active">
<img src="./assets/icon03.png" alt />分析报告
</button>
</div>
</div>
</div>
<div class="title">
<span class="title-one">当前合作限制数据已关联至行政令:</span>
<span class="title-two">《美国联邦通信委员会(FCC)启动程序撤销对 TUV/宁波的认可》2025年10月24日</span>
<img src="./assets/right.png" alt="" />
<img src="./assets/right.png" alt />
</div>
<div class="main">
<div class="left">
<!-- 制裁概况 -->
<div class="left-top">
<img class="img1" src="./assets/bluetitle.png" alt="" />
<img class="img1" src="./assets/bluetitle.png" alt />
<div class="left-top-title">制裁概况</div>
<img class="img2" src="./assets/下载按钮.png" alt="" />
<img class="img3" src="./assets/收藏按钮.png" alt="" />
<img class="img2" src="./assets/下载按钮.png" alt />
<img class="img3" src="./assets/收藏按钮.png" alt />
<div class="left-top-content">
<span
>美国联邦通信委员会(FCC)启动程序撤销对德国莱茵 TÜV
集团/中国检验认证集团(宁波)有限公司作为测试认可实验室的认证。</span
>
<span>
美国联邦通信委员会(FCC)启动程序撤销对德国莱茵 TÜV
集团/中国检验认证集团(宁波)有限公司作为测试认可实验室的认证。
</span>
</div>
<div class="left-top-bottom">
<div><span class="tit">限制时间:</span><span class="tit1">2025年10月24日</span></div>
<div><span class="tit">限制机构:</span><span class="tit1 tit2">美国联邦通信委员会(FCC) ></span></div>
<div><span class="tit">限制手段:</span><span class="tit1">行政令</span></div>
<div><span class="tit">限制领域:</span><span class="tit3">集成电路</span></div>
<div>
<span class="tit">限制时间:</span>
<span class="tit1">2025年10月24日</span>
</div>
<div>
<span class="tit">限制机构:</span>
<span class="tit1 tit2">美国联邦通信委员会(FCC) ></span>
</div>
<div>
<span class="tit">限制手段:</span>
<span class="tit1">行政令</span>
</div>
<div>
<span class="tit">限制领域:</span>
<span class="tit3">集成电路</span>
</div>
</div>
</div>
<!-- 受限实体 -->
<div class="left-bottom">
<img class="img1" src="./assets/bluetitle.png" alt="" />
<img class="img1" src="./assets/bluetitle.png" alt />
<div class="left-bottom-title">受限实体</div>
<img class="img2" src="./assets/下载按钮.png" alt="" />
<img class="img3" src="./assets/收藏按钮.png" alt="" />
<img class="img2" src="./assets/下载按钮.png" alt />
<img class="img3" src="./assets/收藏按钮.png" alt />
<div class="left-bottom-main">
<div v-for="item in dataList" :key="item.id" class="main-box">
<img :src="item.img" alt="" />
<img :src="item.img" alt />
<div class="name">{{ item.name }}</div>
<div class="type">{{ item.type }}</div>
</div>
<img src="./assets/注意.png" alt="" />
<img src="./assets/注意.png" alt />
</div>
</div>
<!-- 规则限制事件脉络 -->
<div class="left-bottom-B">
<img class="img1" src="./assets/bluetitle.png" alt="" />
<img class="img1" src="./assets/bluetitle.png" alt />
<div class="left-bottom-title">规则限制事件脉络</div>
<img class="img2" src="./assets/下载按钮.png" alt="" />
<img class="img3" src="./assets/收藏按钮.png" alt="" />
<img class="img2" src="./assets/下载按钮.png" alt />
<img class="img3" src="./assets/收藏按钮.png" alt />
<div class="left-bottom-main">
<div v-for="item in objList" :key="item.id" class="main-box">
<img :src="item.img" alt="" />
<img :src="item.img" alt />
<div class="time">{{ item.time }}</div>
<div class="name">{{ item.name }}</div>
</div>
<div class="btn">查看更多 <img src="./assets/doubleLine.png" alt="" /></div>
<div class="btn">
查看更多
<img src="./assets/doubleLine.png" alt />
</div>
<div class="line"></div>
</div>
</div>
......@@ -76,21 +95,21 @@
<div class="right">
<!-- 背景分析 -->
<div class="right-bottom">
<img class="img1" src="./assets/bluetitle.png" alt="" />
<img class="img1" src="./assets/bluetitle.png" alt />
<div class="right-bottom-title">背景分析</div>
<div class="right-bottom-content1">
<div class="right-bottom-content1-title">
<span>(一)法律框架 </span>
<img src="./assets/打开按钮.png" alt="" />
</div>
<div class="right-bottom-content1-content">
《法案》第302条授权联邦通信委员会(以下简称委员会或FCC)制定符合公共利益的规则,管理能够发射射频(RF)能量设备的干扰潜力。该法案还允许委员会授权私人机构(测试实验室)进行符合这些规则的合规性测试,并为这些测试实验室建立适当的资质和标准。委员会不会认可未能满足所有适当标准的任何测试实验室,包括与测试实验室的诚信和可靠性相关的标准。委员会的规则部分规定,“确保参与FCC设备授权计划的测试实验室不受对国家安全构成风险的不可信行为者的所有权、指挥或控制。”
<span>(一)法律框架</span>
<img src="./assets/打开按钮.png" alt />
</div>
<div
class="right-bottom-content1-content"
>《法案》第302条授权联邦通信委员会(以下简称委员会或FCC)制定符合公共利益的规则,管理能够发射射频(RF)能量设备的干扰潜力。该法案还允许委员会授权私人机构(测试实验室)进行符合这些规则的合规性测试,并为这些测试实验室建立适当的资质和标准。委员会不会认可未能满足所有适当标准的任何测试实验室,包括与测试实验室的诚信和可靠性相关的标准。委员会的规则部分规定,“确保参与FCC设备授权计划的测试实验室不受对国家安全构成风险的不可信行为者的所有权、指挥或控制。”</div>
</div>
<div class="right-bottom-content2">
<div class="right-bottom-content2-title">
<span>(二)事实背景 </span>
<img src="./assets/打开按钮.png" alt="" />
<span>(二)事实背景</span>
<img src="./assets/打开按钮.png" alt />
</div>
<div class="right-bottom-content2-content">
TUV/宁波是一家位于中国浙江宁波的认可测试实验室,被FCC认可可对各种射频设备进行测试,以确保符合适用的FCC规则。根据美国实验室认可协会(A2LA)的信息,TUV/宁波的认证表明该实验室已按照公认的国际标准ISO/IEC
......@@ -99,8 +118,8 @@
</div>
<div class="right-bottom-content3">
<div class="right-bottom-content3-title">
<span>(二)其他背景 </span>
<img src="./assets/打开按钮.png" alt="" />
<span>(二)其他背景</span>
<img src="./assets/打开按钮.png" alt />
</div>
<div class="right-bottom-content3-content">
中华人民共和国(PRC)是一个禁止实体,根据委员会规则第2.902条的规定进行识别。OET 已初步确定
......@@ -116,28 +135,29 @@
</div>
<!-- 限制条款 -->
<div class="right-top">
<img class="img1" src="./assets/bluetitle.png" alt="" />
<img class="img1" src="./assets/bluetitle.png" alt />
<div class="right-top-title">限制条款</div>
<div class="right-top-content">
<div v-for="item in dataList2" :key="item.id" class="right-top-item">
<span class="id">{{ item.id }}</span>
<span class="name">{{ item.name }}</span>
<img src="./assets/打开按钮.png" alt="" />
<img src="./assets/打开按钮.png" alt />
</div>
</div>
</div>
<!-- 相关举措 -->
<div class="right-top-b">
<img class="img1" src="./assets/bluetitle.png" alt="" />
<img class="img1" src="./assets/bluetitle.png" alt />
<div class="right-top-title">相关举措</div>
<div class="right-top-content">
<div v-for="item in dataList3" :key="item.id" class="right-top-item">
<img :src="item.img" alt="" />
<img :src="item.img" alt />
<div class="name">{{ item.name }}</div>
<div class="time">{{ item.time }}</div>
<div class="type" :class="{ type1: item.type === '行政令', type2: item.type === '法案' }">
{{ item.type }}
</div>
<div
class="type"
:class="{ type1: item.type === '行政令', type2: item.type === '法案' }"
>{{ item.type }}</div>
<div class="content">{{ item.content }}</div>
</div>
</div>
......@@ -159,106 +179,118 @@ import czb from "./assets/财政部.png";
import gh from "./assets/国会.png";
const dataList = ref([
{
id: 1,
name: "中国检验认证集团(宁波)有限公司",
type: "",
img: ningbo
},
{
id: 2,
name: "德国莱茵 TÜV 集团",
type: "",
img: deguo
}
{
id: 1,
name: "中国检验认证集团(宁波)有限公司",
type: "",
img: ningbo
},
{
id: 2,
name: "德国莱茵 TÜV 集团",
type: "",
img: deguo
}
]);
const objList = ref([
{
id: 1,
name: "撤销多家中国实验室对进入美国市场电子产品的测试认证许可。",
time: "2025-08-30",
img: cycle
},
{
id: 2,
name: "禁止被认定存在“国家安全风险”的中国实验室为进入美国市场的电子设备(如手机、电脑)提供FCC要求的合规性测试与认...",
time: "2025-08-30",
img: cycle
},
{
id: 3,
name: "禁止授权进口或销售任何新设备。新规进一步禁止新设备中使用这些清单内公司的零部件,并允许FCC撤销已授权设备的许可。",
time: "2025-08-30",
img: cycle
},
{
id: 4,
name: "撤销或终止中国电信运营商在美国提供国际电信服务的授权。",
time: "2025-08-30",
img: cycle
},
{
id: 5,
name: "禁止使用特定中国技术和设备的公司建造或运营连接美国的通信电缆。",
time: "2025-08-30",
img: cycle
}
{
id: 1,
name: "撤销多家中国实验室对进入美国市场电子产品的测试认证许可。",
time: "2025-08-30",
img: cycle
},
{
id: 2,
name: "禁止被认定存在“国家安全风险”的中国实验室为进入美国市场的电子设备(如手机、电脑)提供FCC要求的合规性测试与认...",
time: "2025-08-30",
img: cycle
},
{
id: 3,
name: "禁止授权进口或销售任何新设备。新规进一步禁止新设备中使用这些清单内公司的零部件,并允许FCC撤销已授权设备的许可。",
time: "2025-08-30",
img: cycle
},
{
id: 4,
name: "撤销或终止中国电信运营商在美国提供国际电信服务的授权。",
time: "2025-08-30",
img: cycle
},
{
id: 5,
name: "禁止使用特定中国技术和设备的公司建造或运营连接美国的通信电缆。",
time: "2025-08-30",
img: cycle
}
]);
const dataList2 = ref([
{
id: 1,
name: "根据本命令,OET认定TUV/宁波没有说明委员会为何不应开始撤销其作为认可测试实验室资格的程序。在其回应中,TUV/宁波声称其不受委员会规则下的禁止实体控制或指挥,但未说明其被禁止实体持有的股权。TUV/宁波的公司治理文件显示,CCIC是公司的股东,并出资占公司创立资本的49%."
},
{
id: 2,
name: "TUV/宁波必须在本命令发布后三十五(35)天内提交回复,说明委员会为何不应撤销其认可。如果未能及时回复或提交说明委员会不应撤销其认可的合理依据的回复,可能会导致撤销认可。公司的回复必须包含一份书面详细事实说明,充分说明公司是否由中华人民共和国拥有、控制或受其指示。"
},
{
id: 3,
name: "OET 根据《法案》第302(e)条以及委员会规则第2.951(d)和(e)条启动了一个程序,以最终确定是否撤销对TUV/Ningbo作为认可测试实验室的认可。此程序为公司提供了额外的通知和机会,以提交书面回应,说明委员会为何不应撤销其当前的认可。"
}
{
id: 1,
name: "根据本命令,OET认定TUV/宁波没有说明委员会为何不应开始撤销其作为认可测试实验室资格的程序。在其回应中,TUV/宁波声称其不受委员会规则下的禁止实体控制或指挥,但未说明其被禁止实体持有的股权。TUV/宁波的公司治理文件显示,CCIC是公司的股东,并出资占公司创立资本的49%."
},
{
id: 2,
name: "TUV/宁波必须在本命令发布后三十五(35)天内提交回复,说明委员会为何不应撤销其认可。如果未能及时回复或提交说明委员会不应撤销其认可的合理依据的回复,可能会导致撤销认可。公司的回复必须包含一份书面详细事实说明,充分说明公司是否由中华人民共和国拥有、控制或受其指示。"
},
{
id: 3,
name: "OET 根据《法案》第302(e)条以及委员会规则第2.951(d)和(e)条启动了一个程序,以最终确定是否撤销对TUV/Ningbo作为认可测试实验室的认可。此程序为公司提供了额外的通知和机会,以提交书面回应,说明委员会为何不应撤销其当前的认可。"
}
]);
const dataList3 = ref([
{
id: 1,
name: "美国商务部工业与安全局发布实体清单,涉及多家中国半导体企业",
time: "2025年9月12日",
content:
"23家中国实体,包括复旦微电旗下多家公司、华岭股份等,指控这些实体“违背美国国家安全或外交政策利益”,包括为中国的...",
type: "行政令",
img: swb
},
{
id: 2,
name: "美国白宫发布总统政令,提出将发展美国人工智能产业硬件支持放在新任期的科技首要地位",
time: "2025年9月11日",
content:
"9个中国实体​(8家企业和1名个人),例如湖北奇卡工业有限公司、广州雅凯国际货运代理有限公司等,指控这些实体为也门胡塞...",
type: "行政令",
img: bg
},
{
id: 3,
name: "美国财政部外国资产控制办公室指控中国企业及船只",
time: "2025年3月13日",
content:
"​4家中国企业和3艘关联船只​(如香港和顺运贸有限公司、华夏贸易有限公司等),指控这些公司拥有或运营向中国运送伊朗石油或...",
type: "行政令",
img: czb
},
{
id: 4,
name: "美国国会通过《芯片科学》法案",
time: "2025年1月3日",
content:
"​多家中国实体,包括成都雷电微力科技股份有限公司、中国科学院长春光学精密机械与物理研究所等,指控这些实体与中国高超音...",
type: "法案",
img: gh
}
{
id: 1,
name: "美国商务部工业与安全局发布实体清单,涉及多家中国半导体企业",
time: "2025年9月12日",
content:
"23家中国实体,包括复旦微电旗下多家公司、华岭股份等,指控这些实体“违背美国国家安全或外交政策利益”,包括为中国的...",
type: "行政令",
img: swb
},
{
id: 2,
name: "美国白宫发布总统政令,提出将发展美国人工智能产业硬件支持放在新任期的科技首要地位",
time: "2025年9月11日",
content:
"9个中国实体​(8家企业和1名个人),例如湖北奇卡工业有限公司、广州雅凯国际货运代理有限公司等,指控这些实体为也门胡塞...",
type: "行政令",
img: bg
},
{
id: 3,
name: "美国财政部外国资产控制办公室指控中国企业及船只",
time: "2025年3月13日",
content:
"​4家中国企业和3艘关联船只​(如香港和顺运贸有限公司、华夏贸易有限公司等),指控这些公司拥有或运营向中国运送伊朗石油或...",
type: "行政令",
img: czb
},
{
id: 4,
name: "美国国会通过《芯片科学》法案",
time: "2025年1月3日",
content:
"​多家中国实体,包括成都雷电微力科技股份有限公司、中国科学院长春光学精密机械与物理研究所等,指控这些实体与中国高超音...",
type: "法案",
img: gh
}
]);
const overviewInfo = ref({})
// const getUrlParams = () => {
// const urlParams = new URLSearchParams(window.location.search);
// sanRecordId.value = urlParams.get("id") || ""
// }
onMounted(() => {
// getUrlParams()
})
</script>
<style lang="scss" scoped>
......
......@@ -6,7 +6,7 @@
<input v-model="input" class="search-input" placeholder="搜索规则限制" />
<div class="search-btn-small" @click="handleSearch">
<div class="search-icon">
<img src="./assets/icons/search-icon.png" alt="" />
<img src="./assets/icons/search-icon.png" alt />
</div>
<div class="search-text">搜索</div>
</div>
......@@ -15,25 +15,25 @@
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">最新动态</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">咨询要闻</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">数据总览</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">资源库</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
</div>
......@@ -55,51 +55,51 @@
<div class="search-main">
<input v-model="input" placeholder="搜索规则限制" class="search-input" />
<div class="search-btn">
<img src="./assets/icons/search-icon.png" alt="" />
<img src="./assets/icons/search-icon.png" alt />
搜索
</div>
</div>
<!-- <div class="search-center">
<div class="search-center">
<div class="search-item">
<div class="search-item-num">190</div>
<div class="search-item-num">{{ statCountInfo.AOCOUNT }}</div>
<div class="search-item-name">规则限制政令</div>
</div>
<div class="search-item">
<div class="search-item-num">125</div>
<div class="search-item-num">{{ statCountInfo.ENTITYCOUNT }}</div>
<div class="search-item-name">规则限制实体</div>
</div>
<div class="search-item">
<div class="search-item-num">18</div>
<div class="search-item-num">{{ statCountInfo.ACTACOUNT }}</div>
<div class="search-item-name">排华科技联盟</div>
</div>
<div class="search-item">
<div class="search-item-num">12</div>
<div class="search-item-num">{{ statCountInfo.COUNTRYCOUNT }}</div>
<div class="search-item-name">排华国家数量</div>
</div>
</div> -->
</div>
<div class="search-bottom">
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">最新动态</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">咨询要闻</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">数据总览</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">资源库</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
<img src="@/assets/icons/arrow-right-icon.png" alt />
</div>
</div>
</div>
......@@ -137,7 +137,7 @@
</template>
<script setup>
import { ref, nextTick } from "vue";
import { ref, nextTick, onMounted } from "vue";
import { useRouter } from "vue-router";
import comTitle from "./common/comTitle.vue";
import newData from "./components/dataNew/index.vue";
......@@ -147,6 +147,7 @@ import resLib from "./components/resLib/index.vue";
import HeaderMenu from "@/components/headerMenu.vue";
import headerInfo from "@/components/headerInfo.vue";
import { useContainerScroll } from "@/hooks/useScrollShow";
import { getStatCount } from '@/api/ruleRestriction/index.js'
// 搜索框
const input = ref("");
......@@ -155,35 +156,59 @@ const { isShow } = useContainerScroll(homeMainRef);
const router = useRouter();
const statCountInfo = ref({})
const getStatCountInfo = async () => {
try {
const res = await getStatCount();
if (res && res.code === 200) {
// console.log('----getStatCountInfo', res.data)
statCountInfo.value = res.data
}
} catch (error) {
console.error("获取首页统计接口失败:", error);
}
}
// 搜索功能
const handleSearch = () => {
console.log("搜索内容:", input.value);
console.log("搜索内容:", input.value);
};
// 锚点跳转
const handleToPosi = id => {
const element = document.getElementById(id);
if (element && homeMainRef.value) {
// 如果当前还未显示吸顶搜索栏,先强制切换状态以稳定布局
if (!isShow.value) {
isShow.value = true;
}
const element = document.getElementById(id);
if (element && homeMainRef.value) {
// 如果当前还未显示吸顶搜索栏,先强制切换状态以稳定布局
if (!isShow.value) {
isShow.value = true;
}
// 使用 nextTick 确保 DOM 状态更新(高度变化生效)后再计算
nextTick(() => {
const containerRect = homeMainRef.value.getBoundingClientRect();
const elementRect = element.getBoundingClientRect();
// 使用 getBoundingClientRect 计算元素相对于容器顶部的绝对距离,不受嵌套布局影响
const top = elementRect.top - containerRect.top + homeMainRef.value.scrollTop;
// 使用 nextTick 确保 DOM 状态更新(高度变化生效)后再计算
nextTick(() => {
const containerRect = homeMainRef.value.getBoundingClientRect();
const elementRect = element.getBoundingClientRect();
// 使用 getBoundingClientRect 计算元素相对于容器顶部的绝对距离,不受嵌套布局影响
const top = elementRect.top - containerRect.top + homeMainRef.value.scrollTop;
homeMainRef.value.scrollTo({
top: top,
behavior: "smooth"
});
});
}
homeMainRef.value.scrollTo({
top: top,
behavior: "smooth"
});
});
}
};
// 返回首页
const handleBackHome = () => {
router.push({
path: "/overview"
});
};
onMounted(async () => {
await getStatCountInfo()
})
</script>
<style scoped lang="scss">
......@@ -220,6 +245,45 @@ const handleToPosi = id => {
width: 960px;
height: 168px;
margin: 0 auto 68px auto;
.search-center {
width: 688px;
height: 48px;
margin: 0 auto;
margin-top: 36px;
display: flex;
justify-content: space-between;
.search-item {
width: 120px;
height: 57px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
.search-item-num {
font-family: Microsoft YaHei;
font-style: Bold;
font-size: 36px;
font-weight: 700;
line-height: 22px;
letter-spacing: 0px;
text-align: center;
color: rgba(5, 95, 194, 1);
}
.search-item-name {
font-family: Microsoft YaHei;
font-style: Regular;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: center;
color: rgba(95, 101, 108, 1);
}
}
}
.search-main {
display: flex;
padding-right: 3px;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论