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