提交 f9bbc15d authored 作者: Vicky's avatar Vicky

Merge branch 'master' of http://8.140.26.4:10003/caijian/risk-monitor into xxh-dev

......@@ -91,4 +91,35 @@ export function getSanctionList(params) {
})
}
//被制裁情况:数据对比
export function getStudyList(params) {
return request({
method: 'GET',
url: `/api/enterprisePage/getStudyList/${params}`,
})
}
//供应链:领域
export function getSupplyAreaList(params) {
return request({
method: 'GET',
url: `/api/enterprisePage/getSupplyAreaList/${params}`,
})
}
//供应链:国家地区
export function getSupplyCountryList(params) {
return request({
method: 'GET',
url: `/api/enterprisePage/getSupplyCountryList/${params}`,
})
}
//供应链:关系
export function getSupplyList(params) {
return request({
method: 'GET',
url: `/api/enterprisePage/getSupplyList/${params.id}`,
params,
})
}
import request from "@/api/request.js";
// 合作限制-首页统计接口
export function getCoopRestrictionStatistics() {
return request({
method: 'GET',
url: `/api/cooperationlimitinfo/getCount`
})
}
// 合作限制-查询最新动态信息接口
export function getCoopRestrictionTrends() {
return request({
method: 'GET',
url: `/api/cooperationlimitinfo/getLatestTrends`
})
}
// 合作限制-查询风险信号接口
/**
* @param {moduleId}
* @header token
*/
export function getCoopRestrictionSignals(params) {
return request({
method: 'GET',
url: `/api/commonFeature/riskSignal/${params.moduleId}`
})
}
// 合作限制-查询新闻资讯接口
/**
* @param {moduleId}
* @header token
*/
export function getCoopRestrictionNews(params) {
return request({
method: 'GET',
url: `/api/commonFeature/news/${params.moduleId}`
})
}
// 合作限制-查询社交媒体接口
/**
* @param {moduleId}
* @header token
*/
export function getCoopRestrictionSocial(params) {
return request({
method: 'GET',
url: `/api/commonFeature/social/${params.moduleId}`
})
}
// 合作限制-各类型合作限制政策对比接口
/**
* @param {years}
* @header token
*/
export function getCoopRestrictionCompare(params) {
return request({
method: 'GET',
url: `/api/cooperationlimitinfo/getLimitCompare`,
params
})
}
// 合作限制-各领域规则分布情况接口
/**
* @param {year}
* @header token
*/
export function getCoopRestrictionDomain(params) {
return request({
method: 'GET',
url: `/api/cooperationlimitinfo/getLimitArea`,
params
})
}
\ No newline at end of file
// 智库概览信息
import request from "@/api/request.js";
//创新主体主页:统计不同创新主体类型对应的主体数量
export function getCountSubjectType() {
return request({
method: 'GET',
url: `/api/innovateSubject/countSubjectType`,
})
}
// 创新主体主页:统计不同地理对应的主体数量
export function getCountGeography() {
return request({
method: 'GET',
url: `/api/innovateSubject/countGeography`,
})
}
//创新主体主页:类型列表
export function getSubjectTypeList() {
return request({
method: 'GET',
url: `/api/innovateSubject/subjectTypeList`,
})
}
//创新主体主页:通过类型分页查询创新主体列表
export function findListBySubjectTypeId(params) {
return request({
method: 'GET',
url: `/api/innovateSubject/findListBySubjectTypeId`,
params
})
}
//创新主体主页:综合排名
export function getOverallRanking(params) {
return request({
method: 'GET',
url: `/api/innovateSubject/overallRanking`,
params
})
}
\ No newline at end of file
......@@ -90,7 +90,7 @@ const headerTitleClasses = computed(() => [
width: 100%;
margin-bottom: 15px;
position: relative;
// margin-bottom: 100px;
margin-bottom: 100px;
}
.container-header {
......
......@@ -1513,20 +1513,24 @@ watch(box8selectetedTime, () => {
});
const handleToPosi = id => {
// 0 618 1240 2350
let top = 0;
switch (id) {
case "position2":
containerRef.value.scrollTop = isShow.value ? 634 : 980;
top = isShow.value ? 634 : 980;
break;
case "position3":
containerRef.value.scrollTop = isShow.value ? 1204 : 1550;
top = isShow.value ? 1204 : 1550;
break;
case "position4":
containerRef.value.scrollTop = isShow.value ? 2334 : 2680;
top = isShow.value ? 2334 : 2680;
break;
default:
containerRef.value.scrollTop = 0;
top = 0;
}
containerRef.value.scrollTo({
top: top,
behavior: "smooth"
});
};
const tabList = ref([
......
......@@ -56,7 +56,7 @@
</defs> -->
<!-- 节点 -->
<circle
v-for="(node, idx) in nodes.slice(0, nodes.length)"
v-for="(node, idx) in nodes"
:key="'circle' + idx"
:cx="node.x"
:cy="node.y"
......@@ -66,7 +66,7 @@
stroke-width="3"
/>
<line
v-for="(node, idx) in nodes.slice(0, nodes.length)"
v-for="(node, idx) in nodes"
:key="'line' + idx"
:x1="node.x"
:y1="node.y + 4"
......@@ -170,9 +170,11 @@ export default {
return `${date.getFullYear()}${date.getMonth() + 1}月`;
},
sortedDataList() {
if (!this.dataList) return [];
if (!this.dataList || !Array.isArray(this.dataList)) return [];
// Clone and sort by date ascending (Old -> New)
return [...this.dataList].sort((a, b) => new Date(a.actionDate) - new Date(b.actionDate));
return [...this.dataList]
.filter(item => item && item.actionDate)
.sort((a, b) => new Date(a.actionDate) - new Date(b.actionDate));
},
nodes() {
// 计算每个节点的坐标(蛇形)
......@@ -180,7 +182,6 @@ export default {
const row = Math.floor(idx / this.maxPerRow);
const col = idx % this.maxPerRow;
let x, y;
// const leftMargin = 150; // 你可以自定义这个值
if (row % 2 === 0) {
x = this.leftMargin + col * this.nodeGapX + 50;
......@@ -191,12 +192,17 @@ export default {
y = 60 + row * this.nodeGapY;
// Format Date: 2025-07-04 -> 7月4日
let formattedDate = "";
if (item.actionDate) {
const dateObj = new Date(item.actionDate);
const formattedDate = `${dateObj.getMonth() + 1}${dateObj.getDate()}日`;
if (!isNaN(dateObj.getTime())) {
formattedDate = `${dateObj.getMonth() + 1}${dateObj.getDate()}日`;
}
}
// Format Votes
let voteString = '';
if (item.agreeVote !== null && item.disagreeVote !== null) {
let voteString = "";
if (item.agreeVote !== null && item.agreeVote !== undefined && item.disagreeVote !== null && item.disagreeVote !== undefined) {
voteString = `${item.agreeVote}票赞成 : ${item.disagreeVote}票反对`;
}
......@@ -238,7 +244,6 @@ export default {
for (let i = 1; i < this.nodes.length; i++) {
const prev = this.nodes[i - 1];
const curr = this.nodes[i];
console.log("prev", prev);
// 判断是否是行尾转折点
const isTurnPoint = i % this.maxPerRow === 0;
......@@ -272,7 +277,8 @@ export default {
},
svgHeight() {
// SVG高度
return Math.ceil(this.dataList.length / this.maxPerRow) * this.nodeGapY + 40;
const listLength = (this.dataList && Array.isArray(this.dataList)) ? this.dataList.length : 0;
return Math.ceil(listLength / this.maxPerRow) * this.nodeGapY + 40;
}
}
};
......
......@@ -12,10 +12,10 @@
<!-- 右侧操作图标 -->
<div class="action-icons">
<label class="checkbox-item" style="display: flex;align-items: center;">
<!-- <label class="checkbox-item" style="display: flex;align-items: center;">
<input type="checkbox" v-model="rule" />
<div style="width: 145px;"> 50%穿透规则影响</div>
</label>
</label> -->
<!-- 搜索框容器 -->
<el-input v-model="searchKeyword" style="height: 28px;width: 200px;" placeholder="搜索内容">
<template #suffix>
......@@ -55,10 +55,14 @@
<div class="filter-section">
<h4 class="filter-title">领域</h4>
<div class="checkbox-group">
<label v-for="(item, index) in domainFilters" :key="'domain-' + index" class="checkbox-item">
<el-checkbox-group v-model="selectedDomain" @change="handleAreaChange">
<el-checkbox :label="item.name + '(' + item.num + ')'" v-for="(item, index) in domainFilters"
:value="item.id" />
</el-checkbox-group>
<!-- <label v-for="(item, index) in domainFilters" :key="'domain-' + index" class="checkbox-item">
<input type="checkbox" v-model="item.checked" />
<span>{{ item.label }}</span>
</label>
</label> -->
</div>
</div>
......@@ -66,10 +70,14 @@
<div class="filter-section country-filter">
<h4 class="filter-title">国家/地区</h4>
<div class="checkbox-group two-columns">
<label v-for="(item, index) in countryFilters" :key="'country-' + index" class="checkbox-item">
<el-checkbox-group v-model="selectedcountry" @change="handleCountryChange">
<el-checkbox :label="item.name + '(' + item.num + ')'" v-for="(item, index) in countryFilters"
:value="item.id" />
</el-checkbox-group>
<!-- <label v-for="(item, index) in countryFilters" :key="'country-' + index" class="checkbox-item">
<input type="checkbox" v-model="item.checked" />
<span>{{ item.label }}</span>
</label>
</label> -->
</div>
</div>
......@@ -77,10 +85,10 @@
<div class="filter-section">
<h4 class="filter-title">上下游</h4>
<div class="checkbox-group">
<label v-for="(item, index) in upstreamFilters" :key="'upstream-' + index" class="checkbox-item">
<input type="checkbox" v-model="item.checked" />
<span>{{ item.label }}</span>
</label>
<el-checkbox-group v-model="selectType" @change="handleTypeChange">
<el-checkbox label="上游" value="supply" />
<el-checkbox label="下游" value="customer" /> </el-checkbox-group>
</div>
</div>
</div>
......@@ -93,28 +101,62 @@
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
import getGraphChart from '../js/graphChart.js'
import { getSupplyAreaList, getSupplyCountryList, getSupplyList } from "@/api/companyPages/index.js";
import { useRouter } from "vue-router";
const router = useRouter();
const rule = ref('true')//
const searchKeyword = ref('')
const domainFilters = ref([
{ label: '工业软件领域 (36)', checked: true },
{ label: '供应链与物流服务领域 (36)', checked: false },
{ label: '人工智能领域 (56)', checked: false },
{ label: '半导体与集成电路领域 (19)', checked: false },
{ label: '航天遥感与量子技术领域 (51)', checked: false }
// { label: '工业软件领域 (36)', checked: true },
// { label: '供应链与物流服务领域 (36)', checked: false },
// { label: '人工智能领域 (56)', checked: false },
// { label: '半导体与集成电路领域 (19)', checked: false },
// { label: '航天遥感与量子技术领域 (51)', checked: false }
])
const selectedDomain = ref([])
const handleGetSupplyAreaList = async () => {
try {
const res = await getSupplyAreaList(router.currentRoute._value.params.id);
console.log("领域", res);
if (res.code === 200 && res.data) {
domainFilters.value = res.data
}
} catch (error) {
console.error("获取领域error", error);
}
};
const handleAreaChange = val => {
handleGetSupplyList()
};
const countryFilters = ref([
{ label: '中国 (36)', checked: false },
{ label: '美国 (36)', checked: false },
{ label: '韩国 (56)', checked: false },
{ label: '日本 (19)', checked: false },
{ label: '中国台湾 (51)', checked: false },
{ label: '德国 (51)', checked: false },
{ label: '荷兰 (12)', checked: false },
{ label: '澳大利亚 (4)', checked: false }
// { label: '中国 (36)', checked: false },
// { label: '美国 (36)', checked: false },
// { label: '韩国 (56)', checked: false },
// { label: '日本 (19)', checked: false },
// { label: '中国台湾 (51)', checked: false },
// { label: '德国 (51)', checked: false },
// { label: '荷兰 (12)', checked: false },
// { label: '澳大利亚 (4)', checked: false }
])
const selectedcountry = ref([])
const handleGetSupplyCountryList = async () => {
try {
const res = await getSupplyCountryList(router.currentRoute._value.params.id);
console.log("领域", res);
if (res.code === 200 && res.data) {
countryFilters.value = res.data
}
} catch (error) {
console.error("获取领域error", error);
}
};
const handleCountryChange = val => {
handleGetSupplyList()
};
const upstreamFilters = ref([
{ label: '核心企业 (36)', checked: false },
{ label: '控股子公司 (36)', checked: false },
......@@ -279,11 +321,61 @@ const setChart = (option, chartId) => {
chart.setOption(option)
return chart
}
onMounted(() => {
// 假设你有 getGraphChart 函数
const selectType = ref([])
const handleTypeChange = val => {
handleGetSupplyList()
};
const handleGetSupplyList = async () => {
try {
let params = {
arealist: selectedDomain.value ? selectedDomain.value.join(",") : null,
countrylist: selectedcountry.value ? selectedcountry.value.join(",") : null,
type: selectType.value.length === 2 ? 'all' : selectType.value ? selectType.value : null,
id: router.currentRoute._value.params.id
}
const res = await getSupplyList(params);
console.log("关系", res);
if (res.code === 200 && res.data) {
// 提取所有公司名称
const allCompanies = new Set(res.data.flatMap(item => [item.orgName, item.otherOrgName]));
const companyMap = {};
let id = 0;
// 创建公司名称到ID的映射
allCompanies.forEach(company => {
companyMap[company] = id++;
});
// 创建nodes数组
const nodes = Array.from(allCompanies, (company, index) => ({
id: index,
name: company,
symbolSize: 30,
value: 8,
symbol: `image://${CompanyImg}` // 假设CompanyImg是一个图片路径变量
}));
// 创建links数组
const links = res.data.map(item => ({
source: companyMap[item.orgName],
target: companyMap[item.otherOrgName]
}));
nodes.value = nodes
links.value = links
const graphOption = getGraphChart(nodes.value, links.value)
setChart(graphOption, "graphChart")
}
} catch (error) {
console.error("获取关系error", error);
}
};
onMounted(() => {
handleGetSupplyAreaList()
handleGetSupplyCountryList()
handleGetSupplyList()
// 临时占位:防止报错
// const placeholderOption = {
......
<template>
<div class="chart-container">
<div v-for="(item, index) in chartData" :key="index" class="chart-card">
<div v-for="(item, index) in rawData" :key="index" class="chart-card">
<!-- 研发投入 -->
<div class="metric-section">
<div class="metric-header">
<span class="title">研发投入</span>
<span class="growth-badge">+13.2%</span>
<span class="growth-badge">{{ item.investmentGrowthRate + ' % ' }}</span>
</div>
<!-- 制裁后 -->
<div class="bar-row">
<div class="year-label">{{ item.year }}</div>
<div style="width: calc(100% - 66px);">
<div class="bar after" :style="{ width: getInvestmentWidth(item.investmentAfter) + '%' }">
<div class="value-label">{{ formatInvestment(item.investmentAfter) }}</div>
<div class="value-label">{{ item.investmentAfter + item.investmentUnit }}</div>
</div>
</div>
</div>
<!-- 制裁前 -->
<div class="bar-row">
<div class="year-label">{{ item.year }}</div>
<div class="year-label">{{ item.previousYear }}</div>
<div style="width: calc(100% - 66px);">
<div class="bar before" :style="{ width: getInvestmentWidth(item.investmentBefore) + '%' }">
<div class="value-label">{{ formatInvestment(item.investmentBefore) }}</div>
<div class="value-label">{{ item.investmentBefore + item.investmentUnit }}</div>
</div>
</div>
......@@ -33,23 +33,23 @@
<div class="metric-section">
<div class="metric-header">
<span class="title">研发人员</span>
<span class="growth-badge">+13.2%</span>
<span class="growth-badge">{{ item.staffGrowthRate + '% ' }}</span>
</div>
<!-- 制裁后 -->
<div class="bar-row">
<div class="year-label">{{ item.year }}</div>
<div style="width: calc(100% - 66px);">
<div class="bar after" :style="{ width: getStaffWidth(item.staffAfter) + '%' }">
<div class="value-label">{{ formatStaff(item.staffAfter) }}</div>
<div class="value-label">{{ item.staffAfter + item.staffmentUnit }}</div>
</div>
</div>
</div>
<!-- 制裁前 -->
<div class="bar-row">
<div class="year-label">{{ item.year }}</div>
<div class="year-label">{{ item.previousYear }}</div>
<div style="width: calc(100% - 66px);">
<div class="bar before" :style="{ width: getStaffWidth(item.staffBefore) + '%' }">
<div class="value-label">{{ formatStaff(item.staffBefore) }}</div>
<div class="value-label">{{ item.staffBefore + item.staffmentUnit }}</div>
</div>
</div>
</div>
......@@ -71,22 +71,71 @@
</template>
<script setup>
import { ref, computed } from 'vue';
import { ref, computed, onMounted } from 'vue';
import { useRouter } from "vue-router";
import { getStudyList } from "@/api/companyPages/index.js";
const router = useRouter();
// 模拟从 JSON 导入(实际可替换为 import data from './rdData.json')
const rawData = [
{ year: "2019", investmentBefore: 1.01, investmentAfter: 1.37, staffBefore: 80000, staffAfter: 96000 },
{ year: "2020", investmentBefore: 1.15, investmentAfter: 1.52, staffBefore: 85000, staffAfter: 102000 },
{ year: "2021", investmentBefore: 1.20, investmentAfter: 1.68, staffBefore: 90000, staffAfter: 110000 },
{ year: "2022", investmentBefore: 1.25, investmentAfter: 1.75, staffBefore: 92000, staffAfter: 115000 },
{ year: "2023", investmentBefore: 1.30, investmentAfter: 1.85, staffBefore: 95000, staffAfter: 120000 }
];
const rawData = ref([
// { year: "2019", investmentBefore: 1.01, investmentAfter: 1.37, staffBefore: 80000, staffAfter: 96000 },
// { year: "2020", investmentBefore: 1.15, investmentAfter: 1.52, staffBefore: 85000, staffAfter: 102000 },
// { year: "2021", investmentBefore: 1.20, investmentAfter: 1.68, staffBefore: 90000, staffAfter: 110000 },
// { year: "2022", investmentBefore: 1.25, investmentAfter: 1.75, staffBefore: 92000, staffAfter: 115000 },
// { year: "2023", investmentBefore: 1.30, investmentAfter: 1.85, staffBefore: 95000, staffAfter: 120000 }
])
const handleGetStudyList = async () => {
try {
const res = await getStudyList(router.currentRoute._value.params.id);
console.log("被制裁情况:数据对比", res);
if (res.code === 200 && res.data) {
// 创建一个映射对象,用于存储分组后的数据
const groupedData = {};
res.data.forEach(item => {
const key = `${item.year}-${item.previousYear}`;
if (!groupedData[key]) {
groupedData[key] = {
year: item.year,
previousYear: item.previousYear,
investmentAfter: 0,
investmentBefore: 0,
investmentGrowthRate: 0,
staffAfter: 0,
staffBefore: 0,
staffGrowthRate: 0
};
}
if (item.type === "研发投入") {
groupedData[key].investmentAfter = item.currentValue;
groupedData[key].investmentBefore = item.previousValue;
groupedData[key].investmentGrowthRate = item.growthRate;
groupedData[key].investmentUnit = item.unit;
} else if (item.type === "研发人员") {
groupedData[key].staffAfter = item.currentValue;
groupedData[key].staffBefore = item.previousValue;
groupedData[key].staffGrowthRate = item.growthRate;
groupedData[key].staffmentUnit = item.unit;
}
});
// 将结果转换为数组
const result = Object.values(groupedData);
rawData.value = result
// rawData.value = result
console.log(rawData.value, 'rawData.valuerawData.value')
}
} catch (error) {
console.error("获取被制裁情况:数据对比error", error);
}
};
const chartData = ref(rawData);
// === 投入相关计算 ===
const maxInvestment = computed(() => {
return Math.max(...chartData.value.flatMap(d => [d.investmentBefore, d.investmentAfter]));
return Math.max(...rawData.value.flatMap(d => [d.investmentBefore, d.investmentAfter]));
});
function getInvestmentWidth(value) {
......@@ -99,7 +148,7 @@ function formatInvestment(value) {
// === 人员相关计算 ===
const maxStaff = computed(() => {
return Math.max(...chartData.value.flatMap(d => [d.staffBefore, d.staffAfter]));
return Math.max(...rawData.value.flatMap(d => [d.staffBefore, d.staffAfter]));
});
function getStaffWidth(value) {
......@@ -109,12 +158,17 @@ function getStaffWidth(value) {
function formatStaff(value) {
return Math.round(value / 1000) + 'k+';
}
onMounted(() => {
handleGetStudyList()
});
</script>
<style scoped>
.chart-container {
display: flex;
flex-wrap: wrap;
/* flex-wrap: wrap; */
overflow: auto;
gap: 24px;
padding: 24px;
}
......
<template>
<div class="data-new">
<div class="left">
<img src="./assets/leftbtn.png" alt="" class="left-btn" />
<img src="./assets/rightbtn.png" alt="" class="right-btn" />
<img src="./assets/leftbtn.png" alt="" class="left-btn" @click="handlePrev" />
<img src="./assets/rightbtn.png" alt="" class="right-btn" @click="handleNext" />
<div class="left-top">
<img src="./assets/icon01.png" alt="" />
<div class="left-top-title">合作限制动态</div>
<div class="more" @click="handleClickToDetail">查看详情 ></div>
</div>
<el-carousel
ref="carouselRef"
height="412px"
direction="horizontal"
:autoplay="true"
:interval="5000"
arrow="never"
indicator-position="none"
@change="handleCarouselChange"
>
<el-carousel-item v-for="(item, index) in coopRestrictionTrends" :key="item.ID || index">
<div class="carousel-item-content">
<div class="left-center">
<img src="./assets/usImg.png" alt="" />
<img :src="item.IMAGEURL || defaultImg" alt="" />
<div class="left-center-main">
<div class="left-center-main-title">保护美国资金与专业知识免受敌对研究利用法案</div>
<div class="left-center-main-title">{{ item.LIMITNAME || "暂无动态" }}</div>
<div class="left-center-main-ul">
<ul>
<li>
<span class="ul-title">数据来源:</span>
<span class="ul-content">美国国会</span>
<span class="ul-content">{{ item.ORGNAME || "未知" }}</span>
</li>
<li>
<span class="ul-title">合作限制类型:</span>
<span class="ul-content">科研合作限制</span>
<span class="ul-content">{{ item.LIMITTYPE || "未知" }}</span>
</li>
<li>
<span class="ul-title">发布日期:</span>
<span class="ul-content">2025年10月7日</span>
<span class="ul-content">{{ item.LIMITDATE || "未知" }}</span>
</li>
<li>
<span class="ul-title">涉及领域</span>
<span class="ul-pie cl1">航空航天</span>
<span class="ul-pie cl2">人工智能</span>
<span class="ul-pie cl3">集成电路</span>
<span class="ul-title">涉及领域:</span>
<div class="ul-tags" v-if="item.AREA">
<span
v-for="(field, fIndex) in (typeof item.AREA === 'string' ? item.AREA.split(',') : item.AREA)"
:key="fIndex"
class="ul-pie"
:class="'cl' + ((fIndex % 3) + 1)"
>
{{ field }}
</span>
</div>
<span v-else class="ul-content">未知</span>
</li>
</ul>
</div>
</div>
<div class="left-center-title">国会法案</div>
<!-- <div class="left-center-title">{{ item.LIMITTYPE }}</div> -->
</div>
<div class="left-bottom">
<ul>
<li class="left-bottom-li">内容摘要:</li>
</ul>
<div class="left-bottom-content">
该法案已被纳入《国防授权法案》(NDAA)的讨论范畴,并已在参议院通过审议
。该法案规定,将禁止任何与中国等被视为“敌对国”有合作关系的科学家获得联邦资助
。其限制范围极其宽泛,从联合研究、合著论文到指导研究生或博士后几乎全覆盖
。更严厉的是,该条款具有追溯效力,可追溯至过去5年的合作。
{{ item.INTRODUCTION || "暂无内容摘要" }}
</div>
</div>
</div>
</el-carousel-item>
<!-- 无数据时的占位展示 -->
<el-carousel-item v-if="coopRestrictionTrends.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>
</el-carousel-item>
</el-carousel>
</div>
<div class="right">
<div class="right-top">
<img src="./assets/icon02.png" alt="" />
<div class="right-top-title">
风险信号
<span>4</span>
<span>{{ riskSignals.length }}</span>
</div>
</div>
<div style="margin: 6px 34px 0 23px">
<div v-for="item in list" :key="item.id" class="right-main" @click="handleClickToDetail()">
<div v-for="item in riskSignals" :key="item.id" class="right-main" @click="handleToRiskDetail">
<div class="main-left" :class="{ cl4: item.title === '特别重大', cl5: item.title === '重大风险' }">
{{ item.title }}
</div>
......@@ -75,10 +116,52 @@
</template>
<script setup>
import { ref } from "vue";
import { ref, onMounted, computed } from "vue";
import router from "@/router";
import { getCoopRestrictionTrends } from "@/api/coopRestriction/coopRestriction.js";
import defaultImg from "./assets/usImg.png";
const coopRestrictionTrends = ref([]);
const carouselRef = ref(null);
const activeIndex = ref(0);
// 获取合作限制-最新动态数据
const getCoopRestrictionTrendsData = async () => {
try {
const res = await getCoopRestrictionTrends();
if (res && res.code === 200) {
coopRestrictionTrends.value = res.data || [];
}
} catch (error) {
console.error("获取合作限制最新动态数据失败:", error);
}
};
const list = ref([
// 轮播图手动切换
const handlePrev = () => {
if (carouselRef.value) {
carouselRef.value.prev();
}
};
const handleNext = () => {
if (carouselRef.value) {
carouselRef.value.next();
}
};
// 轮播切换回调
const handleCarouselChange = (index) => {
activeIndex.value = index;
};
// 左侧展示的主动态
const mainTrend = computed(() => {
if (coopRestrictionTrends.value.length === 0) return null;
return coopRestrictionTrends.value[activeIndex.value] || coopRestrictionTrends.value[0];
});
// 右侧风险信号列表
const riskSignals = ref([
{
id: 1,
title: "特别重大",
......@@ -106,8 +189,19 @@ const list = ref([
]);
// 点击查看详情
const handleClickToDetail = () => {
// router.push("/decreeLayout");
const handleClickToDetail = (item) => {
const activeItem = (item && item.ID) ? item : mainTrend.value;
const id = activeItem?.ID;
if (!id) return;
const curRoute = router.resolve({
path: "/cooperationRestrictions/detail",
query: { id: id },
});
window.open(curRoute.href, "_blank");
};
// 点击风险信号详情
const handleToRiskDetail = () => {
const curRoute = router.resolve("/cooperationRestrictions/detail");
window.open(curRoute.href, "_blank");
};
......@@ -118,6 +212,10 @@ const handleToMoreRiskSignal = () => {
window.open(route.href, "_blank");
};
onMounted(() => {
// 合作限制-最新动态数据-获取数据
getCoopRestrictionTrendsData();
});
</script>
<style scoped lang="scss">
......@@ -146,6 +244,8 @@ const handleToMoreRiskSignal = () => {
top: 223px;
left: 0px;
cursor: pointer;
z-index: 100;
pointer-events: auto;
}
.right-btn {
width: 24px;
......@@ -154,6 +254,8 @@ const handleToMoreRiskSignal = () => {
top: 223px;
right: 0px;
cursor: pointer;
z-index: 100;
pointer-events: auto;
}
.left-top {
width: 100%;
......@@ -178,6 +280,7 @@ const handleToMoreRiskSignal = () => {
right: 40px;
color: rgb(5, 95, 194);
cursor: pointer;
z-index: 101;
}
.left-top-title {
margin-left: 60px;
......@@ -193,6 +296,10 @@ const handleToMoreRiskSignal = () => {
padding: 11px 16px;
}
}
.carousel-item-content {
width: 100%;
height: 100%;
}
.left-center {
width: 967px;
height: 208px;
......@@ -224,12 +331,13 @@ const handleToMoreRiskSignal = () => {
list-style-position: inside;
li {
width: 100%;
height: 24px;
min-height: 24px;
margin-bottom: 12px;
display: flex;
align-items: flex-start;
.ul-title {
display: inline-block;
flex-shrink: 0;
width: 120px;
height: 24px;
font-size: 16px;
font-weight: 700;
font-family: "Microsoft YaHei";
......@@ -237,19 +345,28 @@ const handleToMoreRiskSignal = () => {
color: rgb(59, 65, 75);
}
.ul-content {
flex: 1;
color: rgb(59, 65, 75);
font-family: "Microsoft YaHei";
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
.ul-tags {
flex: 1;
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.ul-pie {
display: inline-block;
box-sizing: border-box;
padding: 2px 8px;
border: 1px solid;
border-radius: 4px;
margin-right: 8px;
font-size: 14px;
line-height: 18px;
white-space: nowrap;
}
.cl1 {
border-color: rgba(186, 224, 255, 1);
......
......@@ -4,7 +4,7 @@
<div class="left-title">
<img src="./assets/icon01.png" alt="" />
<div class="tit">各类型合作限制政策对比</div>
<el-select v-model="value" placeholder="Select" class="select">
<el-select v-model="value" placeholder="Select" class="select" @change="getCoopRestrictionCompareData">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
......@@ -16,7 +16,7 @@
<div class="right-title">
<img src="./assets/icon02.png" alt="" />
<div class="tit">各领域规则分布情况</div>
<el-select v-model="value1" placeholder="Select" class="select">
<el-select v-model="value1" placeholder="Select" class="select" @change="getCoopRestrictionDomainData">
<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
......@@ -30,27 +30,119 @@
<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import * as echarts from "echarts";
import { getCoopRestrictionCompare, getCoopRestrictionDomain } from "@/api/coopRestriction/coopRestriction";
const value = ref("近十年");
const value1 = ref("2025年");
const options = [
{
value: "近十年",
label: "近十年"
},
{
value: "近五年",
label: "近五年"
// 合作限制-各领域规则分布情况接口
const coopRestrictionDomain = ref([]);
const getCoopRestrictionDomainData = async () => {
try {
const res = await getCoopRestrictionDomain({
year: value1.value
});
if (res && res.code === 200) {
coopRestrictionDomain.value = res.data || [];
}
} catch (error) {
console.error("获取合作限制各领域规则分布情况数据失败:", error);
}
};
// 合作限制-各类型合作限制政策对比接口
const coopRestrictionCompare = ref([]);
const getCoopRestrictionCompareData = async () => {
try {
const res = await getCoopRestrictionCompare({
years: value.value
});
if (res && res.code === 200) {
coopRestrictionCompare.value = res.data || [];
}
} catch (error) {
console.error("获取合作限制各类型合作限制政策对比数据失败:", error);
}
};
const value = ref(10);
const value1 = ref("2026");
const options = [
{ value: 1, label: "近一年" },
{ value: 2, label: "近两年" },
{ value: 3, label: "近三年" },
{ value: 4, label: "近四年" },
{ value: 5, label: "近五年" },
{ value: 10, label: "近十年" },
{ value: 15, label: "近十五年" },
{ value: 20, label: "近二十年" }
];
const options1 = [
{
value: "2025年",
value: "2026",
label: "2026年"
},
{
value: "2025",
label: "2025年"
},
{
value: "2024",
value: "2024",
label: "2024年"
},
{
value: "2023",
label: "2023年"
},
{
value: "2022",
label: "2022年"
},
{
value: "2021",
label: "2021年"
},
{
value: "2020",
label: "2020年"
},
{
value: "2019",
label: "2019年"
},
{
value: "2018",
label: "2018年"
},
{
value: "2017",
label: "2017年"
},
{
value: "2016",
label: "2016年"
},
{
value: "2015",
label: "2015年"
},
{
value: "2014",
label: "2014年"
},
{
value: "2013",
label: "2013年"
},
{
value: "2012",
label: "2012年"
},
{
value: "2011",
label: "2011年"
},
{
value: "2010",
label: "2010年"
}
];
......@@ -214,7 +306,14 @@ const initRightChart = () => {
rightChart.setOption(option);
};
onMounted(() => { initLeftChart(); initRightChart(); });
onMounted(() => {
// 合作限制-各类型合作限制政策对比接口
getCoopRestrictionCompareData();
// 合作限制-各领域规则分布情况接口
getCoopRestrictionDomainData();
initLeftChart();
initRightChart();
});
onBeforeUnmount(() => { window.removeEventListener("resize", handleResize); if (leftChart) { leftChart.dispose(); leftChart = null; } if (rightChart) { rightChart.dispose(); rightChart = null; } });
</script>
......@@ -259,7 +358,7 @@ onBeforeUnmount(() => { window.removeEventListener("resize", handleResize); if (
color: rgb(5, 95, 194);
}
.select {
width: 120px;
width: 150px;
height: 28px;
padding: 0px 12px;
position: absolute;
......@@ -307,7 +406,7 @@ onBeforeUnmount(() => { window.removeEventListener("resize", handleResize); if (
color: rgb(5, 95, 194);
}
.select {
width: 120px;
width: 150px;
height: 28px;
padding: 0px 12px;
position: absolute;
......
......@@ -95,7 +95,7 @@
</template>
<script setup>
import { ref } from "vue";
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import comTitle from "./common/comTitle.vue";
import newData from "./components/dataNew/index.vue";
......
<template>
<div class="home-wrapper">
<div class="home-header">
<div class="search-header" v-show="isShow">
<div class="home-main-header-center">
<el-input v-model="searchExportControlText" style="width: 800px; height: 100%" placeholder="搜索出口管制" />
<div class="search">
<div class="search-icon">
<img src="@/assets/icons/search-icon.png" alt="" />
</div>
<div class="search-text" @click="handleSearch">搜索</div>
</div>
</div>
<div class="home-main-header-btn-box">
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">{{ "最新动态" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">{{ "资讯要闻" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">{{ "数据总览" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">{{ "资源库" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
</div>
</div>
<div class="home-header" v-show="!isShow">
<div class="header-item">国家科技安全</div>
<div class="header-item">></div>
<div class="header-item back-item" @click="handleBackHome">中美博弈概览</div>
<div class="header-item">></div>
<div class="header-item">出口管制</div>
</div>
<div class="home-main">
<div class="home-main" ref="homeMainRef" :class="{ 'scroll-main': isShow }">
<div class="home-main-header">
<div class="home-main-header-center">
<!-- <el-input
v-model="searchExportControlText"
style="width: 100%; height: 48px"
size="large"
placeholder="搜索出口管制调查"
:suffix-icon="Search"
/> -->
<el-input v-model="searchExportControlText" style="width: 800px; height: 100%" placeholder="搜索出口管制调查" />
<div class="home-main-header-center" v-show="!isShow">
<el-input v-model="searchExportControlText" style="width: 800px; height: 100%" placeholder="搜索出口管制" />
<div class="search">
<div class="search-icon">
<img src="@/assets/icons/search-icon.png" alt="" />
......@@ -25,40 +55,26 @@
<div class="search-text" @click="handleSearch">搜索</div>
</div>
</div>
<!-- <div class="home-main-header-footer">
<div class="home-main-header-footer-item">
<div class="item-top">1096</div>
<div class="item-footer">实体清单</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">2633</div>
<div class="item-footer">商业管制清单</div>
</div>
<div class="home-main-header-footer-item">
<div class="item-top">162</div>
<div class="item-footer">关键和新型技术清单</div>
</div>
</div> -->
<div class="home-main-header-btn-box">
<div class="btn" @click="scrollToTop('position1')">
<div class="home-main-header-btn-box" v-show="!isShow">
<div class="btn" @click="handleToPosi('position1')">
<div class="btn-text">{{ "最新动态" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="scrollToTop('position2')">
<div class="btn" @click="handleToPosi('position2')">
<div class="btn-text">{{ "资讯要闻" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="scrollToTop('position3')">
<div class="btn-text">{{ "统计概览" }}</div>
<div class="btn" @click="handleToPosi('position3')">
<div class="btn-text">{{ "数据总览" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
</div>
</div>
<div class="btn" @click="scrollToTop('position4')">
<div class="btn" @click="handleToPosi('position4')">
<div class="btn-text">{{ "资源库" }}</div>
<div class="btn-icon">
<img src="@/assets/icons/arrow-right-icon.png" alt="" />
......@@ -557,9 +573,15 @@
</div>
</div>
<div class="right-footer">
<div class="total-count">{{ totalAll }}项调查</div>
<el-pagination v-model:current-page="currentPageAll" :page-size="pageSizeAll" :total="totalAll"
layout="prev, pager, next" background @current-change="handlePageChangeAll" />
<div class="total-count">{{ totalAll }}</div>
<el-pagination
v-model:current-page="currentPageAll"
:page-size="pageSizeAll"
:total="totalAll"
layout="prev, pager, next"
background
@current-change="handlePageChangeAll"
/>
</div>
</div>
</div>
......@@ -607,6 +629,9 @@
<script setup>
import { onMounted, ref, computed, reactive, shallowRef, watch } from "vue";
import scrollToTop from "@/utils/scrollToTop";
import { useContainerScroll } from "@/hooks/useScrollShow";
const homeMainRef = ref(null);
const { isShow } = useContainerScroll(homeMainRef);
import * as echarts from "echarts";
import setChart from "@/utils/setChart";
import { ElMessage, ElMessageBox } from "element-plus";
......@@ -658,6 +683,19 @@ import {
getExportControlList
} from "@/api/exportControl";
const handleToPosi = id => {
const element = document.getElementById(id);
if (element && homeMainRef.value) {
const containerRect = homeMainRef.value.getBoundingClientRect();
const elementRect = element.getBoundingClientRect();
const top = elementRect.top - containerRect.top + homeMainRef.value.scrollTop;
homeMainRef.value.scrollTo({
top: top,
behavior: "smooth"
});
}
};
// 跳转到单项制裁页面
const handleToRiskSignalDetail = item => {
const routeData = router.resolve({
......@@ -1185,6 +1223,7 @@ const fetchSanctionList = async () => {
const handlePageChangeAll = val => {
currentPageAll.value = val;
fetchSanctionList();
handleToPosi("position4");
};
watch(
......@@ -1316,8 +1355,8 @@ const resourceTabs = [
{ label: "全部制裁", value: "all", disabled: false },
{ label: "实体清单", value: "entity", disabled: false },
{ label: "商业管制清单", value: "commerce", disabled: true },
{ label: "关键与新兴技术清单", value: "tech", disabled: true },
{ label: "军事最终用户清单", value: "military", disabled: true }
// { label: "关键与新兴技术清单", value: "tech", disabled: true },
// { label: "军事最终用户清单", value: "military", disabled: true }
];
const activeResourceTab = ref("all");
......@@ -3233,4 +3272,102 @@ const handleMediaClick = item => {
}
}
}
.search-header {
width: 100%;
height: 144px;
background: #fff;
overflow: hidden;
.home-main-header-center {
margin-top: 20px;
margin-left: 200px;
width: 800px;
height: 48px;
border-radius: 10px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
padding: 1px;
position: relative;
border: 1px solid transparent;
&:hover {
border: 1px solid var(--color-main-active);
}
.search {
position: absolute;
right: -1px;
top: 0px;
width: 120px;
height: 46px;
border-radius: 10px;
background: var(--color-main-active);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.search-icon {
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
}
}
.search-text {
margin-left: 8px;
height: 22px;
color: #fff;
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 22px;
}
}
}
.home-main-header-btn-box {
margin-top: 20px;
margin-left: 200px;
display: flex;
gap: 16px;
.btn {
display: flex;
align-items: center;
gap: 9px;
width: 160px;
height: 48px;
border: 1px solid #aed6ff;
box-sizing: border-box;
border-radius: 24px;
background: #e7f3ff;
cursor: pointer;
position: relative;
&:hover {
background: #cae3fc;
}
.btn-text {
width: 80px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
line-height: 48px;
margin-left: 36px;
text-align: center;
}
.btn-icon {
position: absolute;
top: 16px;
right: 19px;
width: 6px;
height: 12px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
.scroll-main {
height: calc(100% - 144px) !important;
}
</style>
......@@ -30,7 +30,7 @@
<div class="item-position"></div>
<div class="content">
<div class="info">
<div class="title">2025年新增</div>
<div class="title">{{ currentYear }}年新增</div>
</div>
<div class="number">
<span class="num">{{ totalCount.latestYearCount }}</span>
......@@ -43,7 +43,7 @@
<div class="content">
<div class="info">
<div class="title">近期制裁新增</div>
<div class="subtitle">2025年11月12日</div>
<!-- <div class="subtitle">{{ totalCount.latestTime }}</div> -->
</div>
<div class="number">
<span class="num">{{ totalCount.latestTimeCount }}</span>
......@@ -342,38 +342,28 @@ const regionTime = ref("all");
const domainTime = ref("all");
const typeTime = ref("all");
const currentYear = new Date().getFullYear();
const timeOptions = [
{ label: "全部时间", value: "all" },
{ label: "2025年", value: "2025" },
{ label: "2024年", value: "2024" },
{ label: "2023年", value: "2023" },
{ label: "2022年", value: "2022" },
{ label: "2021年", value: "2021" },
{ label: "2020年", value: "2020" },
{ label: "2019年", value: "2019" },
{ label: "2018年", value: "2018" },
{ label: "2017年", value: "2017" },
{ label: "2016年", value: "2016" },
{ label: "2015年", value: "2015" }
];
for (let i = 0; i <= 10; i++) {
const year = currentYear - i;
timeOptions.push({ label: `${year}年`, value: year.toString() });
}
const sanctionCountChartRef = ref(null);
const mapChartRef = ref(null);
const domainChartRef = ref(null);
const typeChartRef = ref(null);
const getBarColor = index => {
if (index === 0) return "linear-gradient(90deg, rgba(255, 77, 79, 0) 0%, rgba(255, 77, 79, 1) 100%)";
if (index === 1 || index === 2) return "linear-gradient(90deg, rgba(255, 172, 77, 0) 0%, rgba(255, 172, 77, 1) 100%)";
return "linear-gradient(90deg, rgba(5, 95, 194, 0) 0%, rgba(5, 95, 194, 1) 100%)";
};
const updateSanctionCountChart = () => {
if (!sanctionCountChartRef.value) return;
let chart = echarts.getInstanceByDom(sanctionCountChartRef.value);
......
......@@ -82,7 +82,7 @@
</div>
</div>
<div class="left-footer">
<div class="total-count">{{ totalAll }}调查</div>
<div class="total-count">{{ totalAll }}</div>
<el-pagination
v-model:current-page="currentPageAll"
:page-size="pageSizeAll"
......@@ -291,6 +291,18 @@ watch([selectedDomain, onlyChina], () => {
const handlePageChangeAll = val => {
currentPageAll.value = val;
getSanctionUpdate();
const container = document.querySelector(".entity-list");
const target = document.querySelector(".left-bottom");
if (container && target) {
const containerRect = container.getBoundingClientRect();
const targetRect = target.getBoundingClientRect();
// 148是吸顶头部的高度,减去它以避免标题被遮挡
const top = targetRect.top - containerRect.top + container.scrollTop - 148;
container.scrollTo({
top: top,
behavior: "smooth"
});
}
};
// 获取实体清单发布机构
......
......@@ -84,11 +84,11 @@ const headerNavList = ref([
imgActive: icon2Active,
title: "深度挖掘"
},
{
img: icon3,
imgActive: icon3Active,
title: "影响分析"
}
// {
// img: icon3,
// imgActive: icon3Active,
// title: "影响分析"
// }
])
......@@ -103,11 +103,16 @@ const headerNavList = ref([
.entity-list{
width: 100%;
height: 100%;
overflow-y: auto;
.header{
width: 100%;
height: 148px;
background-color: #fff;
padding-top: 16px;
position: sticky;
top: 0;
z-index: 1000;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.05);
.header-title{
width: 1601px;
height: 72px;
......@@ -214,7 +219,8 @@ const headerNavList = ref([
}
.main{
width: 100%;
height: calc(100% - 148px);
height: auto;
min-height: calc(100% - 148px);
background-color: #F7F8F9;
}
}
......
......@@ -34,7 +34,7 @@
</div>
<div class="number">
<span class="num">{{ totalCount.techDomainCount }}</span>
<span class="unit"></span>
<span class="unit"></span>
</div>
</div>
</div>
......@@ -45,9 +45,9 @@
<div class="box"></div>
<div class="text">制裁实体领域分布情况</div>
<div class="right-group">
<el-select v-model="domainTime" class="time-select" placeholder="请选择">
<!-- <el-select v-model="domainTime" class="time-select" placeholder="请选择">
<el-option v-for="item in timeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-select> -->
<div class="btn">
<img src="../../assets/数据库按钮.png" alt="" />
<img src="../../assets/下载按钮.png" alt="" />
......@@ -73,9 +73,9 @@
<div class="box"></div>
<div class="text">制裁实体类型分布情况</div>
<div class="right-group">
<el-select v-model="typeTime" class="time-select" placeholder="请选择">
<!-- <el-select v-model="typeTime" class="time-select" placeholder="请选择">
<el-option v-for="item in timeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-select> -->
<div class="btn">
<img src="../../assets/数据库按钮.png" alt="" />
<img src="../../assets/下载按钮.png" alt="" />
......@@ -99,7 +99,7 @@
<div class="main-item">
<div class="title-com">
<div class="box"></div>
<div class="text">制裁实体国家分布</div>
<div class="text">制裁实体国家分布情况</div>
<div class="right-group">
<div class="btn">
<img src="../../assets/数据库按钮.png" alt="" />
......@@ -141,9 +141,9 @@
<div class="box"></div>
<div class="text">制裁实体地域分布情况</div>
<div class="right-group">
<el-select v-model="regionTime" class="time-select" placeholder="请选择">
<!-- <el-select v-model="regionTime" class="time-select" placeholder="请选择">
<el-option v-for="item in timeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-select> -->
<div class="btn">
<img src="../../assets/数据库按钮.png" alt="" />
<img src="../../assets/下载按钮.png" alt="" />
......
......@@ -272,7 +272,8 @@ const getUrlParams = () => {
sanRecordId.value = urlParams.get("id") || ""
}
const activeTab = ref(["实体穿透分析", "重点实体识别"]);
// const activeTab = ref(["实体穿透分析", "重点实体识别"]);
const activeTab = ref(["实体穿透分析"]);
const activeIndex = ref(0);
const rightActiveTab = ref("supplyChain");
......
......@@ -514,30 +514,26 @@ onMounted(() => {
margin: 0 auto;
padding-top: 16px;
padding-bottom: 50px;
.main {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
.left {
width: 520px;
height: 1119px;
.left-top {
width: 100%;
height: 582px;
height: auto;
padding-bottom: 20px;
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background-color: #fff;
margin-bottom: 16px;
.left-top-title {
padding: 22px 20px 22px 27px;
width: 100%;
height: 286px;
height: auto;
border-bottom: 1px solid rgb(234, 236, 238);
display: flex;
flex-direction: column;
......@@ -569,7 +565,7 @@ onMounted(() => {
font-size: 16px;
font-family: "Microsoft YaHei";
line-height: 24px;
overflow: hidden; // Ensure it respects the container width
overflow: hidden;
&.link {
color: rgb(5, 95, 194);
......@@ -591,26 +587,10 @@ onMounted(() => {
&.tags {
gap: 8px;
overflow-x: auto; // Allow horizontal scrolling
white-space: nowrap; // Prevent wrapping
padding-bottom: 4px; // Add some space for scrollbar
/* Custom Scrollbar */
&::-webkit-scrollbar {
height: 4px;
}
&::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 2px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
flex-wrap: wrap;
overflow: visible;
.tag {
flex-shrink: 0; // Prevent tags from shrinking
padding: 1px 8px;
background: rgba(246, 250, 255, 1);
border-radius: 4px;
......
......@@ -162,11 +162,16 @@ onMounted(() => {
.entity-list{
width: 100%;
height: 100%;
overflow-y: auto;
.header{
width: 100%;
height: 148px;
background-color: #fff;
padding-top: 16px;
position: sticky;
top: 0;
z-index: 1000;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.05);
.header-title{
width: 1601px;
height: 72px;
......@@ -300,7 +305,8 @@ onMounted(() => {
}
.main{
width: 100%;
height: calc(100% - 148px);
height: auto;
min-height: calc(100% - 148px);
background-color: #F7F8F9;
}
}
......
......@@ -3,7 +3,7 @@
<div class="header">
<div class="header-top">
<div class="header-top-left">
<img :src="thinkInfo.contentUrl" alt="" />
<img :src="thinkInfo.imageUrl" alt="" />
<div>
<div class="title">{{ thinkInfo.name }}</div>
<div class="en-title">
......
......@@ -88,13 +88,13 @@
{{ val }}
</div>
</div>
<div class="more">
<!-- <div class="more">
<img src="@/assets/icons/open.png" alt="" />
</div>
</div> -->
</div>
</div>
<div class="box3-main-footer">
<div class="info">{{ total }}条建议</div>
<div class="info">{{ total }}</div>
<div class="page-box">
<el-pagination :page-size="12" background layout="prev, pager, next" :total="total"
@current-change="handleCurrentChange" :current-page="currentPage" />
......
......@@ -73,14 +73,26 @@
<img src="./images/search-icon.png" alt="" />
</div>
</div>
<div class="select-box">
<el-select v-model="selectedYear" placeholder="选择时间" style="width: 120px" @click="handleGetThinkPolicy()">
<el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="sort" placeholder="发布时间" style="width: 120px; margin-left: 8px">
<div class="paixu-btn" @click="handleSwithSort()">
<div class="icon1">
<img v-if="sort" src="@/assets/icons/shengxu1.png" alt="" />
<img v-else src="@/assets/icons/jiangxu1.png" alt="" />
</div>
<div class="text">{{ "发布时间" }}</div>
<div class="icon2">
<img v-if="sort" src="@/assets/icons/shengxu2.png" alt="" />
<img v-else src="@/assets/icons/jiangxu2.png" alt="" />
</div>
</div>
<!-- <el-select v-model="sort" placeholder="发布时间" style="width: 120px; margin-left: 8px">
<el-option @click="handleGetThinkPolicy()" :key="true" label="正序" :value="true" />
<el-option @click="handleGetThinkPolicy()" :key="false" label="倒序" :value="false" />
</el-select>
</el-select> -->
</div>
</div>
<div class="bottom-main">
......@@ -145,7 +157,7 @@
</div>
</div>
<div class="right-footer">
<div class="info">{{ total }}篇政策建议</div>
<div class="info">{{ total }}</div>
<div class="page-box">
<el-pagination :page-size="12" background layout="prev, pager, next" :total="total"
@current-change="handleCurrentChange" :current-page="currentPage" />
......@@ -547,7 +559,12 @@ const toDetaile = (id) => {
}
const total = ref(0);
const sort = ref(true);
const sort = ref(false);
const handleSwithSort = () => {
sort.value = !sort.value;
handleGetThinkPolicy()()
};
const currentPage = ref(1);
// 处理页码改变事件
const handleCurrentChange = page => {
......@@ -738,6 +755,59 @@ onMounted(() => {
right: 33px;
width: 100px;
height: 28px;
.paixu-btn {
display: flex;
width: 120px;
height: 32px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
&:hover {
background: var(--color-bg-hover);
}
cursor: pointer;
.icon1 {
width: 11px;
height: 14px;
margin-top: 10px;
margin-left: 9px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 19px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
margin-top: 7px;
margin-left: 9px;
}
.icon2 {
width: 10px;
height: 5px;
margin-top: 5px;
margin-left: 13px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
}
......@@ -775,6 +845,60 @@ onMounted(() => {
.select-box {
margin-right: 5px;
display: flex;
.paixu-btn {
display: flex;
width: 120px;
height: 32px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
&:hover {
background: var(--color-bg-hover);
}
cursor: pointer;
.icon1 {
width: 11px;
height: 14px;
margin-top: 10px;
margin-left: 9px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 19px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
margin-top: 7px;
margin-left: 9px;
}
.icon2 {
width: 10px;
height: 5px;
margin-top: 5px;
margin-left: 13px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
......@@ -794,37 +918,57 @@ onMounted(() => {
.select-box {
margin-top: 21px;
.select-box-header {
.paixu-btn {
display: flex;
gap: 17px;
width: 120px;
height: 32px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
.icon {
margin-top: 4px;
width: 8px;
height: 16px;
background: var(--color-main-active);
border-radius: 0 4px 4px 0;
&:hover {
background: var(--color-bg-hover);
}
.title {
height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 1px;
text-align: left;
cursor: pointer;
.icon1 {
width: 11px;
height: 14px;
margin-top: 10px;
margin-left: 9px;
img {
width: 100%;
height: 100%;
}
}
.select-main {
margin-left: 25px;
width: 160px;
.text {
height: 19px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
margin-top: 7px;
margin-left: 9px;
}
.select-main1 {
width: 100px;
.icon2 {
width: 10px;
height: 5px;
margin-top: 5px;
margin-left: 13px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
......
......@@ -10,7 +10,7 @@
<div class="header-item">科技智库</div>
</div>
<div class="home-main-header-center">
<el-input v-model="searchThinktankText" style="width: 838px; height: 100%" placeholder="搜索科技人物及观点" />
<el-input v-model="searchThinktankText" style="width: 838px; height: 100%" placeholder="搜索智库报告" />
<div class="search">
<div class="search-icon">
<img src="./assets/images/search-icon.png" alt="" />
......@@ -78,12 +78,12 @@
<div class="title-right">{{ item.country }}</div>
</div>
<el-popover effect="dark" :content="item.desc" placement="top-start">
<!-- <el-popover effect="dark" :content="item.desc" placement="top-start">
<template #reference>
<div class="content">{{ item.desc }}</div>
</template>
</el-popover>
</el-popover> -->
<div class="content">{{ item.desc }}</div>
<div class="tag-box">
<div class="tag" :class="{
tag1: val.status === 1,
......@@ -177,14 +177,16 @@
{{ item.status || "一般风险" }}
</div>
<div class="item-right">
<el-popover effect="dark" :width="500" :content="item.title" placement="top-start">
<!-- <el-popover effect="dark" :width="500" :content="item.title" placement="top-start">
<template #reference>
<div class="text">
{{ item.title }}
</div>
</template>
</el-popover>
</el-popover> -->
<div class="text">
{{ item.title }}
</div>
<div class="time">{{ item.time }}</div>
</div>
</div>
......@@ -220,11 +222,12 @@
<div class="time">{{ news.newsOrg }}</div>
</div>
<el-popover effect="dark" :width="700" :content="news.newsContent" placement="top-start">
<!-- <el-popover effect="dark" :width="700" :content="news.newsContent" placement="top-start">
<template #reference>
<div class="right-footer">{{ news.newsContent }}</div>
</template>
</el-popover>
</el-popover> -->
<div class="right-footer">{{ news.newsContent }}</div>
</div>
</div>
</div>
......@@ -350,6 +353,8 @@
<div class="home-main-footer">
<DivideHeader id="position4" class="divide-header" :titleText="'资源库'"></DivideHeader>
<div class="home-main-footer-header">
<div class="btn-box">
<div class="btn" :class="{ btnActive: activeCate === cate }" v-for="(cate, index) in categoryList"
......@@ -357,10 +362,23 @@
{{ cate }}
</div>
</div>
<el-select v-model="sort" placeholder="发布时间" style="width: 120px; margin-left: 8px">
<div class="select-box">
<div class="paixu-btn" @click="handleSwithSort()">
<div class="icon1">
<img v-if="sort" src="@/assets/icons/shengxu1.png" alt="" />
<img v-else src="@/assets/icons/jiangxu1.png" alt="" />
</div>
<div class="text">{{ "发布时间" }}</div>
<div class="icon2">
<img v-if="sort" src="@/assets/icons/shengxu2.png" alt="" />
<img v-else src="@/assets/icons/jiangxu2.png" alt="" />
</div>
</div>
</div>
<!-- <el-select v-model="sort" placeholder="发布时间" style="width: 120px; margin-left: 8px">
<el-option @click="handleGetetThinkTankReport()" :key="true" label="正序" :value="true" />
<el-option @click="handleGetetThinkTankReport()" :key="false" label="倒序" :value="false" />
</el-select>
</el-select> -->
</div>
<div class="home-main-footer-main">
<div class="left">
......@@ -411,14 +429,16 @@
<div class="footer-card-top">
<img :src="item.imageUrl" alt="" />
</div>
<el-popover effect="dark" :content="item.name" placement="top-start">
<!-- <el-popover effect="dark" :content="item.name" placement="top-start">
<template #reference>
<div class="footer-card-title">
{{ item.name }}
</div>
</template>
</el-popover>
</el-popover> -->
<div class="footer-card-title">
{{ item.name }}
</div>
<div class="footer-card-footer">
<div class="time">{{ item.times }}</div>
<div class="from">{{ item.thinkTankName }}</div>
......@@ -1283,6 +1303,11 @@ const selectedPubTimeList = ref([""]);
const checkAllTime = ref(false);
const isIndeterminateTime = ref(true);
const sort = ref(false);
const handleSwithSort = () => {
sort.value = !sort.value;
handleGetetThinkTankReport()()
};
const handleCheckAllChangeTime = val => {
// console.log(val, "handleCheckAllChange");
if (val) {
......@@ -2808,6 +2833,7 @@ onMounted(async () => {
}
.box6-main {
margin: 15px;
height: 360px;
}
}
......@@ -3034,6 +3060,8 @@ onMounted(async () => {
overflow: hidden;
background: rgba(247, 248, 249, 1);
.home-main-footer-header {
width: 1600px;
height: 42px;
......@@ -3081,6 +3109,59 @@ onMounted(async () => {
height: 42px;
box-sizing: border-box;
padding: 5px 0;
.paixu-btn {
display: flex;
width: 120px;
height: 32px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
&:hover {
background: var(--color-bg-hover);
}
cursor: pointer;
.icon1 {
width: 11px;
height: 14px;
margin-top: 10px;
margin-left: 9px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 19px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
margin-top: 7px;
margin-left: 9px;
}
.icon2 {
width: 10px;
height: 5px;
margin-top: 5px;
margin-left: 13px;
img {
width: 100%;
height: 100%;
}
}
}
}
}
......
......@@ -3,6 +3,13 @@ const getPieChart = (data) => {
series: [
{
type: 'pie',
// grid: {
// top: '15%',
// right: '15%',
// bottom: '5%',
// left: '15%',
// containLabel: true
// },
radius: [70, 100],
height: '100%',
left: 'center',
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论