提交 47cc3016 authored 作者: 李顺's avatar 李顺

合并分支 'ls_dev' 到 'master'

Ls dev 查看合并请求 !95
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
...@@ -107,6 +107,7 @@ const getMainDataList = async () => { ...@@ -107,6 +107,7 @@ const getMainDataList = async () => {
} }
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 => ({
......
...@@ -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>
<div class="social-item-main" :style="{ backgroundImage: `url(${socialConfig[index].bg})` }"> </div>
<div class="cl1">{{ item.name }}</div> <!-- <div class="mask">
<div class="cl2">{{ item.content }}</div> <img src="./assets/title02.png" alt />
<div class="cl3">{{ item.time }}</div> <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>
<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> </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 },
{ icon: title02, bg: title02bg },
{ icon: title03, bg: title03bg }
];
// 规则限制-查询新闻资讯接口
const getRuleRestrictionNewsData = async () => {
try { try {
const res = await getRuleRestrictionNews({ moduleId: "0108" }); const res = await getNews('0108');
// console.log('----res', res)
if (res && res.code === 200) { if (res && res.code === 200) {
leftList.value = (res.data || []).map(item => ({ // console.log('----getNewsList', res.data)
id: item.newsId, leftList.value = res.data
title: item.newsTitle,
content: item.newsContent,
time: `${item.newsDate}${item.newsOrg ? " · " + item.newsOrg : ""}`,
image: item.newsImage
}));
} }
} catch (error) { } catch (error) {
console.error("获取规则限制新闻资讯数据失败:", error); console.error("获取新闻资讯接口失败:", error);
} }
}; }
// 规则限制-查询社交媒体接口 const getRemarksList = async () => {
const getRuleRestrictionSocialData = async () => {
try { try {
const res = await getRuleRestrictionSocialMedia({ moduleId: "0108" }); const res = await getRemarks('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");
const d = date.getDate().toString().padStart(2, "0");
const hh = date.getHours().toString().padStart(2, "0");
const mm = date.getMinutes().toString().padStart(2, "0");
const formattedTime = `${y}-${m}-${d} ${hh}:${mm} · 发布于${item.orgName}`;
return {
id: item.personId,
name: item.personName,
content: item.remarks,
time: formattedTime,
image: item.personImage
};
});
} }
} catch (error) { } catch (error) {
console.error("获取规则限制社交媒体数据失败:", 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;
display: flex;
img {
width: 36px;
height: 36px;
margin-right: 8.5px;
}
.trump-main {
width: 695.6px;
height: 148px;
background-image: url("./assets/title01bg.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);
}
}
}
.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; 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 { .malaby-main {
width: 695.6px; width: 695.6px;
height: 98px;
background-image: url("./assets/title03bg.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; 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>
<el-carousel
ref="carouselRef"
height="412px"
direction="horizontal"
:autoplay="true"
:interval="5000"
arrow="never"
indicator-position="none"
@change="handleCarouselChange"
>
<el-carousel-item v-for="(item, index) in riskSignalList" :key="item.RULEID || index">
<div class="carousel-item-content">
<div class="left-center"> <div class="left-center">
<img :src="item.PUBLISHORGIMGURL || defaultImg" alt="" /> <img src="./assets/usImg.png" alt />
<div class="left-center-main"> <div class="left-center-main">
<div class="left-center-main-title"> <div class="left-center-main-title">{{ latestUpdateList[latestUpdateIndex].RULENAMEZH }}</div>
{{ item.RULENAMEZH || "暂无动态" }}
</div>
<div class="left-center-main-ul"> <div class="left-center-main-ul">
<ul> <ul>
<li> <li>
<span class="ul-title">发布机构:</span> <span class="ul-title">发布机构:</span>
<span class="ul-content">{{ item.PUBLISHORGNAME || "未知" }}</span> <span class="ul-content">{{ latestUpdateList[latestUpdateIndex].PUBLISHORGNAME }}</span>
</li> </li>
<li> <li>
<span class="ul-title">发布日期:</span> <span class="ul-title">发布日期:</span>
<span class="ul-content">{{ item.PUBLISHDATE || "未知" }}</span> <span class="ul-content">{{ latestUpdateList[latestUpdateIndex].PUBLISHDATE }}</span>
</li> </li>
<li> <li>
<span class="ul-title">涉及领域:</span> <span class="ul-title">涉及领域:</span>
<div class="ul-tags" v-if="item.ruleAreas && item.ruleAreas.length > 0">
<span <span
v-for="(field, fIndex) in item.ruleAreas" class="ul-pie cl1"
:key="fIndex" v-for="item in latestUpdateList[latestUpdateIndex].ruleAreas"
class="ul-pie" >{{ item }}</span>
:class="'cl' + ((fIndex % 4) + 1)" <!-- <span class="ul-pie cl2">集成电路</span>
> <span class="ul-pie cl3">新材料</span>
{{ field }} <span class="ul-pie cl4">生物科技</span>-->
</span>
</div>
<span v-else class="ul-content">未知</span>
</li> </li>
<li> <li>
<span class="ul-title">限制实体:</span> <span class="ul-title">限制实体:</span>
<span class="ul-content"> <span
{{ class="ul-content"
item.ruleEntities && item.ruleEntities.length > 0 v-for="item in latestUpdateList[latestUpdateIndex].ruleEntities"
? item.ruleEntities.map(e => e.ORGNAME).join("、") >{{ item.ORGNAME }} &nbsp;</span>
: "未知"
}}
</span>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
<!-- <div class="left-center-title">国会法案</div> -->
</div> </div>
<div class="left-bottom"> <div class="left-bottom">
<ul> <ul>
<li class="left-bottom-li">内容摘要:</li> <li class="left-bottom-li">内容摘要:</li>
</ul> </ul>
<div class="left-bottom-content"> <div class="left-bottom-content">{{ latestUpdateList[latestUpdateIndex].RULEINTRODUCTION }}</div>
{{ 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>
</div>
</el-carousel-item>
</el-carousel>
</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();
// console.log('------getLatestUpdateInfo res', res)
if (res && res.code === 200) { if (res && res.code === 200) {
riskSignalList.value = res.data || []; console.log('----getLatestUpdateInfo', res.data)
latestUpdateList.value = res.data
} }
} catch (error) { } catch (error) {
console.error("获取规则限制动态数据失败:", 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)
list.value = res.data
} }
}; } catch (error) {
const handleNext = () => { console.error("获取风险信号接口失败:", error);
if (carouselRef.value) {
carouselRef.value.next();
} }
}; }
// 轮播切换回调 // // 跳转详情
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({
...@@ -231,6 +201,11 @@ const handleToMoreRiskSignal = () => { ...@@ -231,6 +201,11 @@ 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;
...@@ -543,39 +518,28 @@ const handleToMoreRiskSignal = () => { ...@@ -543,39 +518,28 @@ const handleToMoreRiskSignal = () => {
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 {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
.main-center { .main-center {
flex: 1; width: 347px;
height: 30px; // height: 30px;
font-size: 16px; font-size: 16px;
font-weight: 400; font-weight: 400;
font-family: "Microsoft YaHei"; font-family: "Microsoft YaHei";
line-height: 30px; line-height: 30px;
color: rgb(59, 65, 75); color: rgb(59, 65, 75);
margin-right: 10px; margin-right: 2px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
} }
.main-right { .main-right {
width: 100px; width: 60px;
height: 24px; // height: 24px;
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(132, 136, 142); color: rgb(132, 136, 142);
text-align: right; text-align: right;
flex-shrink: 0;
}
} }
} }
.right-mainbtn { .right-mainbtn {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<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" />
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
</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" />
...@@ -31,44 +31,41 @@ ...@@ -31,44 +31,41 @@
</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: "集成电路"
} }
]; ];
...@@ -77,32 +74,84 @@ const rightChartRef = ref(null); ...@@ -77,32 +74,84 @@ const rightChartRef = ref(null);
let leftChart; let leftChart;
let rightChart; let rightChart;
const initLeftDonut = () => {
const colors = [
{
name: '集成电路',
value: "rgba(105, 177, 255, 1)",
},
{
name: '新一代通信网络',
value: "rgba(135, 232, 222, 1)",
},
{
name: '人工智能',
value: "rgba(255, 192, 105, 1)",
},
{
name: '能源',
value: "rgba(89, 126, 247, 1)",
},
{
name: '先进制造',
value: "rgba(214, 228, 255, 1)",
},
{
name: '生物科技',
value: "rgba(255, 120, 117, 1)",
},
{
name: '航空航天',
value: "rgba(179, 127, 235, 1)",
},
{
name: '新材料',
value: "rgba(255, 163, 158, 1)",
}
];
const initLeftDonut = async () => {
if (!leftChartRef.value) return; if (!leftChartRef.value) return;
if (leftChart) leftChart.dispose(); if (leftChart) leftChart.dispose();
leftChart = echarts.init(leftChartRef.value); leftChart = echarts.init(leftChartRef.value);
const data = [ let data = []
{ name: "集成电路", value: 50 },
{ name: "人工智能", value: 46 }, try {
{ name: "通信网络", value: 40 }, const params = {
{ name: "能源", value: 32 }, year: value1.value
{ name: "先进制造", value: 31 }, }
{ name: "生物科技", value: 31 }, const res = await getAreaDistribution(params);
{ name: "航空航天", value: 30 }, if (res && res.code === 200) {
{ name: "新材料", value: 24 } console.log('----getAreaDistribution', res.data)
]; for (let i = 0; i < res.data.length; i++) {
const colors = [ let item = {
"rgba(105, 177, 255, 1)", // 集成电路 name: '',
"rgba(255, 192, 105, 1)", // 人工智能 value: 0
"rgba(135, 232, 222, 1)", // 通信网络 }
"rgba(89, 126, 247, 1)", // 能源
"rgba(214, 228, 255, 1)", // 先进制造 item.name = res.data[i].AREANAME
"rgba(255, 120, 117, 1)", // 生物科技 item.value = res.data[i].AREACOUNT
"rgba(179, 127, 235, 1)", // 航空航天 item.itemStyle = {
"rgba(255, 163, 158, 1)" // 新材料 color: getColor(colors, item.name)
]; }
data.push(item)
}
}
} catch (error) {
console.error("获取限制领域分布情况接口失败:", error);
}
// console.log('----data', data)
// const data = [
// { name: "集成电路", value: 50 },
// { name: "人工智能", value: 46 },
// { name: "通信网络", value: 40 },
// { name: "能源", value: 32 },
// { name: "先进制造", value: 31 },
// { name: "生物科技", value: 31 },
// { name: "航空航天", value: 30 },
// { name: "新材料", value: 24 }
// ];
const option = { const option = {
color: colors,
tooltip: { trigger: "item", formatter: ({ name, value, percent }) => `${name}<br/>${value}${percent}%` }, tooltip: { trigger: "item", formatter: ({ name, value, percent }) => `${name}<br/>${value}${percent}%` },
series: [{ series: [{
type: "pie", type: "pie",
...@@ -144,30 +193,98 @@ const initLeftDonut = () => { ...@@ -144,30 +193,98 @@ const initLeftDonut = () => {
}, },
data: data.map((d, i) => ({ data: data.map((d, i) => ({
...d, ...d,
labelLine: { lineStyle: { color: colors[i], width: 1 } } labelLine: { lineStyle: { color: getColor(colors, d.name), width: 1 } }
})) }))
}] }]
}; };
leftChart.setOption(option); 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 seriesData = []
let maxValue = 0
try {
const params = {
year: value.value,
type: value2.value
}
const res = await getEntityChangeTrend(params);
console.log('-----getEntityChangeTrendList res', res)
if (res && res.code === 200) {
console.log('----getEntityChangeTrendList', res.data)
// 对查询到的数据进行分类
for (let i = 0; i < res.data.length; i++) {
const item = res.data[i]
maxValue = Math.max(item.ENTITYCOUNT, maxValue)
// 优先遍历seriesData中是否已经存在name对象
const index = seriesData.findIndex((ele) => ele.name === item.AREANAME)
// console.log('---seriesData', i, JSON.stringify(seriesData), index)
if (index !== -1) {
const yearIndex = years.findIndex((y) => y === item.YEAR)
seriesData[index].data[yearIndex] = item.ENTITYCOUNT
} else {
const data = new Array(value.value).fill(0)
const yearIndex = years.findIndex((y) => y === item.YEAR)
data[yearIndex] = item.ENTITYCOUNT
// 新建
const color_ = getColor(colors, item.AREANAME)
// 以逗号划分为数组并修改最后一部分的值
const colorArray = color_.split(',')
const colorArray1 = JSON.parse(JSON.stringify(colorArray))
const colorArray2 = JSON.parse(JSON.stringify(colorArray))
colorArray1[colorArray1.length - 1] = '0.5)'
colorArray2[colorArray2.length - 1] = '0.1)'
const color1 = colorArray1.join(',')
const color2 = colorArray2.join(',')
console.log(item.AREANAME, '----color1 color2', color1, color2)
const options = {
name: item.AREANAME,
type: 'line',
data: data,
smooth: false,
symbol: 'circle',
symbolSize: 6,
lineStyle: { width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: color1 },
{ offset: 1, color: color2 }
])
},
itemStyle: {
color: color_
}
}
seriesData.push(options)
}
}
}
} catch (error) {
console.error("获取受限实体数量变化趋势接口失败:", error);
}
const option = { const option = {
color: seriesData.map(s => s.color), color: colors.map((item) => {
return item.value
}),
legend: { legend: {
top: 10, top: 10,
left: 'center', left: 'center',
...@@ -207,8 +324,8 @@ const initRightLine = () => { ...@@ -207,8 +324,8 @@ const initRightLine = () => {
yAxis: { yAxis: {
type: 'value', type: 'value',
min: 0, min: 0,
max: 200, max: maxValue * 1.5,
interval: 40, interval: maxValue * 0.5,
axisLine: { show: false }, axisLine: { show: false },
axisTick: { show: false }, axisTick: { show: false },
axisLabel: { axisLabel: {
...@@ -228,111 +345,53 @@ const initRightLine = () => { ...@@ -228,111 +345,53 @@ const initRightLine = () => {
type: 'line' type: 'line'
} }
}, },
series: [ series: seriesData
{
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)' }
])
}
},
{
name: '能源',
type: 'line',
data: seriesData[5].data,
smooth: false,
symbol: 'circle',
symbolSize: 6,
lineStyle: { width: 2 },
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(206, 79, 81, 0.25)' },
{ offset: 1, color: 'rgba(206, 79, 81, 0.05)' }
])
}
}
]
}; };
rightChart.setOption(option); rightChart.setOption(option);
}; };
const getColor = (colors, name) => {
const index = colors.findIndex((i) => i.name === name)
if (index !== -1) {
return colors[index].value
} else {
return "rgba(105, 177, 255, 1)"
}
}
const handleResize = () => { const handleResize = () => {
if (leftChart) leftChart.resize(); if (leftChart) leftChart.resize();
if (rightChart) rightChart.resize(); if (rightChart) rightChart.resize();
}; };
onMounted(() => { const getEntityChangeTrendList = async () => {
initLeftDonut(); try {
initRightLine(); const params = {
year: value.value,
type: value2.value
}
const res = await getEntityChangeTrend(params);
console.log('-----getEntityChangeTrendList res', res)
if (res && res.code === 200) {
console.log('----getEntityChangeTrendList', res.data)
}
} catch (error) {
console.error("获取受限实体数量变化趋势接口失败:", error);
}
}
watch(value1, () => {
initLeftDonut()
})
watch([value, value2], () => {
initRightLine()
})
onMounted(async () => {
await initLeftDonut();
await initRightLine();
window.addEventListener("resize", handleResize); window.addEventListener("resize", handleResize);
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
......
...@@ -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">
<img class="img-style" :src="ele.COUNTRYIMAGE" v-for="ele in item.countries" alt />
</div>
<div style="width: calc(100% - 60px)">
<div style="display: flex; justify-content: space-between;">
<div> <div>
<span class="name">{{ item.name }}</span <span class="name">{{ item.ACTANAME }}</span>
><span class="abb">{{ item.abb }}</span> <span class="abb">{{ item.ACTASHORTNAMEEN }}</span>
<div class="compose">{{ item.compose }}</div>
</div> </div>
<div class="type">
<div <div
class="type" v-for="(ele, index) in item.area"
:class="{ :key="index"
type1: item.type === '通信网络', :class="{ type1: ele !== '', type3: ele === '' }"
type2: item.type === '集成电路', >{{ ele }}</div>
type3: item.type === '' </div>
}" </div>
> <div class="compose">{{ getCompose(item) }}</div>
{{ item.type }}
</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,34 +159,29 @@ ...@@ -140,34 +159,29 @@
</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
} }
}); });
}; };
...@@ -179,343 +193,308 @@ const handleClickNav = item => { ...@@ -179,343 +193,308 @@ const handleClickNav = item => {
activeItem.value = item; activeItem.value = item;
if (item === "规则限制政令") { if (item === "规则限制政令") {
isShow.value = true; isShow.value = true;
getRuleLimitListApi()
} else { } else {
isShow.value = false; 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, "value": "0103",
name: "美国" "label": "韩国",
checked: false
}, },
{ {
id: 3, "value": "0104",
name: "日本" "label": "日本",
checked: false
}, },
{ {
id: 4, "label": "印度",
name: "韩国" "value": "0119",
checked: false
}, },
{ {
id: 5, "value": "0203",
name: "英国" "label": "瑞典",
checked: false
}, },
{ {
id: 6, "value": "0204",
name: "澳大利亚" "label": "芬兰",
checked: false
}, },
{ {
id: 7, "label": "英国",
name: "新西兰" "value": "0217",
checked: false
}, },
{ {
id: 8, "value": "0220",
name: "加拿大" "label": "荷兰",
checked: false
}, },
{ {
id: 9, "value": "0222",
name: "欧盟" "label": "法国",
checked: false
}, },
{ {
id: 10, "value": "0401",
name: "中国台湾" "label": "澳大利亚",
} checked: false
]);
const mainDataList = ref([
{
id: 1,
title: "美国FDA:针对两家中国第三方检测机构的数据完整性问题采取行动",
content:
"FDA因发现数据伪造或无效问题,向两家中国第三方检测公司(天津中联科技检测有限公司和苏州大学卫生与环境技术研究所)正式发出“一般信函”。",
date: "2025年10月15日",
domain: ["生物科技"],
type: "行政令",
img: fda
},
{
id: 2,
title: "美国商务部:扩大实体清单制裁范围,对中企子公司实施同等管制",
content:
"任何被列入美国出口管制“实体清单”或“军事最终用户清单”的企业,如果其直接或间接持有另一家公司 ​50%或以上的股权,那么这家被控股的公司也将自动受到与清单上母公司同等的出口管制限制",
date: "2025年9月30日",
domain: ["生物科技"],
type: "301调查",
img: swb
}, },
{ {
id: 3, "value": "0501",
title: "美国商务部:出台全面半导体出口管制", "label": "加拿大",
content: "美国商务部宣称将“至少每年”更新一次管制规则,以堵塞已发现的政策“漏洞”。", checked: false
date: "2025年9月15日",
domain: ["生物科技"],
type: "行政令",
img: swb
}, },
{ {
id: 4, "value": "0502",
title: "美国FCC:出台电信设备市场准入认证新规", "label": "美国",
content: "将国家安全审查全面嵌入设备授权程序,对实验室资质、测试标准以及供应链设置严格限制。", checked: false
date: "2025年9月8日",
domain: ["生物科技", "通信网络"],
type: "行政令",
img: fcc
}, },
{ {
id: 5, "value": "010101",
title: "美国FCC:发布“清洁购物车”行动,要求电商平台下架违规中国电子产品", "label": "中国台湾",
content: checked: false
"在亚马逊、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 mainDataList = ref([]);
{
id: 1, const unionDataList = ref([])
name: "AI-RAN联盟",
abb: "QUAD", // 筛选逻辑处理
compose: "2024年成立 · 美国、英国、日本、韩国、法国、加拿大等10国", const handleFilterChange = (item, list) => {
content: // 如果点击的是"全部"
"由英伟达牵头,联合软银、亚马逊云科技、微软、爱立信、诺基亚、三星、T-Mobile等多家行业领导者成立了的人工智能无线接入网络技术联盟。", if (item.value === 'all') {
type: "通信网络", if (item.checked) {
img: flag01 // 选中全部,取消其他所有
}, list.forEach(i => {
{ if (i.value !== 'all') i.checked = false;
id: 2, });
name: "Next G联盟", } else {
abb: "", // 取消全部(通常不允许全部取消,至少得选一个,这里如果取消全部,就默认为全部选中)
compose: "2021年成立 · 美国、瑞典、芬兰、韩国", item.checked = true;
content: "在6G技术研发和未来标准制定上抢先布局,旨在主导6G发展方向,其联盟的排他性被解读为针对中国。",
type: "通信网络",
img: flag02
},
{
id: 3,
name: "美日印澳“四边机制”",
abb: "QUAD",
compose: "2021年成立 · 美国、日本、印度、澳大利亚",
content: "在地区安全、基础设施、新兴技术和供应链(特别是半导体)等领域开展排他性合作,筹备构建“印太版北约” 。",
type: "集成电路",
img: flag03
},
{
id: 4,
name: "美国半导体联盟",
abb: "SIAC",
compose: "2021年成立 · 美国、韩国、中国台湾、荷兰",
content:
"初始核心任务是游说美国政府对本土芯片产业提供补贴(如500亿美元的《芯片法案》),但其成员构成未纳入中国大陆企业,具有明显的“排华”倾向。",
type: "集成电路",
img: flag04
},
{
id: 5,
name: "Next G联盟",
abb: "",
compose: "2021年成立 · 美国、瑞典、芬兰、韩国",
content: "在6G技术研发和未来标准制定上抢先布局,旨在主导6G发展方向,其联盟的排他性被解读为针对中国。",
type: "通信网络",
img: flag05
},
{
id: 6,
name: "芯片四方联盟",
abb: "Chip 4",
compose: "2020年成立 · 美国、日本、韩国、中国台湾",
content: "构建将中国大陆排除在外的半导体供应链体系,意图在芯片设计、生产到供应环节形成闭环,限制先进芯片技术对华出口。",
type: "集成电路",
img: flag06
},
{
id: 7,
name: "美英澳三边安全伙伴关系",
abb: "AUKUS",
compose: "2020年成立 · 美国、英国、澳大利亚",
content: "美英两国支持澳大利亚建立核潜艇部队,旨在深化三国在安全和防务能力上的合作。",
type: "",
img: flag07
},
{
id: 8,
name: "印太经济框架",
abb: "IPEF",
compose: "2020年成立 · 美国、英国、澳大利亚",
content: "重点在供应链领域制定新协议,增强透明度与安全性,确保对半导体等关键产品和技术的获取,推动供应链“去中国化”。",
type: "集成电路",
img: flag08
},
{
id: 9,
name: "清洁网络计划",
abb: "",
compose: "2019年成立 · 美国、英国、荷兰",
content:
"在全球5G网络部署和软件应用生态中排除中国的企业和设备,涉及电信运营商、移动应用、应用商店、云服务和海底光缆等多个层面。",
type: "通信网络",
img: flag09
},
{
id: 10,
name: "清洁网络计划",
abb: "",
compose: "2019年成立 · 美国、英国、荷兰",
content:
"在全球5G网络部署和软件应用生态中排除中国的企业和设备,涉及电信运营商、移动应用、应用商店、云服务和海底光缆等多个层面。",
type: "通信网络",
img: flag09
} }
]); } else {
// 点击的是具体项
if (item.checked) {
// 选中具体项,取消"全部"
const allItem = list.find(i => i.value === 'all');
if (allItem) allItem.checked = false;
} else {
// 取消具体项,检查是否还有选中的
const anyChecked = list.some(i => i.checked);
if (!anyChecked) {
const allItem = list.find(i => i.value === 'all');
if (allItem) allItem.checked = true;
}
}
}
// 重置页码并查询
currentPage.value = 0;
if (isShow.value) {
getRuleLimitListApi();
} else {
getACTAListInfo()
}
};
const getRuleLimitListApi = async () => {
// 处理科技领域筛选
let techDomains = [];
const allTech = techFields.value.find(item => item.value === 'all');
if (!allTech || !allTech.checked) {
techDomains = techFields.value
.filter(item => item.checked && item.value !== 'all')
.map(item => item.value);
}
// 处理发布时间时间筛选
let years = [];
const allTime = dataList.value.find(item => item.value === 'all');
if (!allTime || !allTime.checked) {
years = dataList.value
.filter(item => item.checked && item.value !== 'all')
.map(item => item.value);
}
const params = {
areas: techDomains.length > 0 ? techDomains.join(',') : undefined,
years: years.length > 0 ? years.join(',') : undefined,
keywords: undefined,
sortOrder: value.value,
sortField: 'date',
currentPage: currentPage.value,
pageSize: pageSize.value
};
try {
console.log('-----getRuleLimitList params', params)
const res = await getRuleLimitList(params);
console.log('-----getRuleLimitList res', res)
if (res.code === 200) {
console.log('-----getRuleLimitListApi', res.data)
total.value = res.data.numberOfElements
mainDataList.value = res.data.content
}
} catch (error) {
console.error("获取规则限制政令列表查询接口接口失败:", error);
}
}
const getACTAListInfo = async () => {
// 处理科技领域筛选
let techDomains = [];
const allTech = techFields.value.find(item => item.value === 'all');
if (!allTech || !allTech.checked) {
techDomains = techFields.value
.filter(item => item.checked && item.value !== 'all')
.map(item => item.value);
}
// 处理发布时间时间筛选
let years = [];
const allTime = dataList.value.find(item => item.value === 'all');
if (!allTime || !allTime.checked) {
years = dataList.value
.filter(item => item.checked && item.value !== 'all')
.map(item => item.value);
}
// 处理国家筛选
let countries = []
const allCountry = dataList3.value.find(item => item.value === 'all')
if (!allCountry || !allCountry.checked) {
countries = dataList3.value.filter(item => item.checked && item.value !== 'all').map(item => item.value)
}
const params = {
areas: techDomains.length > 0 ? techDomains.join(',') : undefined,
years: years.length > 0 ? years.join(',') : undefined,
keywords: undefined,
countries: countries,
sortOrder: value.value,
sortField: 'date',
currentPage: currentPageACTA.value,
pageSize: pageSizeACTA.value
};
try {
console.log('-----getACTAList params', params)
const res = await getACTAList(params);
console.log('-----getACTAList res', res)
if (res.code === 200) {
console.log('-----getACTAListInfo', res.data)
unionDataList.value = res.data.content
totalACTA.value = res.data.numberOfElements
}
} catch (error) {
console.error("获取规则限制政令列表查询接口接口失败:", error);
}
}
const getCompose = (item) => {
if (item) {
const countries = item.countries.map(i => i.COUNTRYNAME)
return item.ACTAYEAR + '年成立 · ' + countries.join('、')
}
}
watch(value, () => {
if (isShow.value) {
getRuleLimitListApi()
} else {
getACTAListInfo()
}
})
const getDate = (item) => {
if (item && item.PUBLISHDATE) {
let year = item.PUBLISHDATE.split('-')[0]
let month = item.PUBLISHDATE.split('-')[1]
let day = +item.PUBLISHDATE.split('-')[2]
return year + '年' + month + '月' + day + '日'
}
}
onMounted(async () => {
await getRuleLimitListApi()
try {
const res = await getAcTAAllcountry();
console.log('-----getAcTAAllcountry res', res)
if (res.code === 200) {
console.log('-----getAcTAAllcountry', res.data)
}
} catch (error) {
console.error("获取规则限制政令列表查询接口接口失败:", error);
}
})
const total = ref(1205); const 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>
<style scoped lang="scss"> <style scoped lang="scss">
...@@ -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>
...@@ -259,6 +279,18 @@ const dataList3 = ref([ ...@@ -259,6 +279,18 @@ const dataList3 = ref([
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,6 +156,20 @@ const { isShow } = useContainerScroll(homeMainRef); ...@@ -155,6 +156,20 @@ 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);
...@@ -184,6 +199,16 @@ const handleToPosi = id => { ...@@ -184,6 +199,16 @@ const handleToPosi = id => {
} }
}; };
// 返回首页
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论