提交 3729dff3 authored 作者: 付康's avatar 付康

合并分支 'zz-dev' 到 'master'

feat:智库概览页,智库详情报告分析 查看合并请求 !174
......@@ -83,6 +83,15 @@ export function getThinkTankReport(params) {
})
}
// 智库概览:政策建议(资源库-政策建议)
export function getThinkTankOverviewPolicy(params) {
return request({
method: 'GET',
url: `/api/thinkTankOverview/policy`,
params
})
}
/********* 智库信息 */
//智库百科:获取全局信息
export function getThinkTankSummary(params) {
......@@ -119,6 +128,13 @@ export function getThinkPolicyIndustry(params) {
url: `/api/thinkTankInfo/policyIndustry/${params.id}/${params.year}`,
})
}
//提出政策建议涉及部门分布
export function getPolicyAdviceDeptDistribution(params){
return request({
method: 'GET',
url: `/api/thinkTankInfo/policyDepartment/${params.id}/${params.year}`,
})
}
//获取相关政策领域分布
export function getThinkPolicyIndustryTotal(params) {
......@@ -201,6 +217,15 @@ export const getThinkTankReportSummary = (params) => {
}
);
}
//智库报告:获取相关报告
export const getThinkTankReportRelated = (params) => {
return request(
{
method: 'GET',
url: `/api/thinkTankReport/related/${params}`,
}
);
}
//获取报告原文
export const getThinkTankReportcontentUrl = (params) => {
......
......@@ -80,6 +80,7 @@ const handleToNewsAnalysis = (item, index) => {
flex-direction: column;
gap: 0 !important;
overflow: hidden;
border: 1px solid rgba(234, 236, 238, 1) !important;
.news-header {
height: 48px !important;
......@@ -149,6 +150,7 @@ const handleToNewsAnalysis = (item, index) => {
&:hover {
background: var(--color-bg-hover);
.right-top .title {
text-decoration: underline;
color: rgb(5, 95, 194) !important;
......
......@@ -50,7 +50,7 @@
</template>
<script setup>
import NewsList from "@/components/NewsList.vue";
import NewsList from "@/components/base/newsList/index.vue";
import { ref, onMounted } from "vue";
import router from '@/router'
import { getCoopRestrictionNews, getCoopRestrictionSocial } from '@/api/coopRestriction/coopRestriction'
......
......@@ -50,25 +50,12 @@
<div class="home-main" ref="homeMainRef">
<div class="home-top-bg"></div>
<div class="home-main-header">
<SearchContainer
style="margin-bottom: 0; margin-top: 48px; height: fit-content"
v-if="homeMainRef"
placeholder="搜索出口管制"
:containerRef="homeMainRef"
areaName="实体清单"
/>
<SearchContainer style="margin-bottom: 0; margin-top: 48px; height: fit-content" v-if="homeMainRef"
placeholder="搜索出口管制" :containerRef="homeMainRef" areaName="实体清单" />
<div class="home-main-header-footer-info">
<InfoCard
v-for="(item, index) in infoList"
:key="item.id"
:title="item.nameZh"
:subtitle="item.nameAbbr"
:description="item.description"
:quantity="item.postCount"
unit="次"
:color="infoListColor[index]"
@click="handleToEntityListNoId(item)"
/>
<InfoCard v-for="(item, index) in infoList" :key="item.id" :title="item.nameZh" :subtitle="item.nameAbbr"
:description="item.description" :quantity="item.postCount" unit="次" :color="infoListColor[index]"
@click="handleToEntityListNoId(item)" />
</div>
</div>
......@@ -94,15 +81,8 @@
<img src="./assets/images/box1-right.png" alt="" />
</div>
</div>
<el-carousel
ref="carouselRef"
height="370px"
:autoplay="true"
:interval="3000"
arrow="never"
indicator-position="none"
@change="handleCarouselChange"
>
<el-carousel ref="carouselRef" height="370px" :autoplay="true" :interval="3000" arrow="never"
indicator-position="none" @change="handleCarouselChange">
<el-carousel-item v-for="(item, index) in entitiesDataInfoList" :key="item.id + index">
<div>
<div class="box1-top">
......@@ -120,11 +100,8 @@
</div>
<div class="box1-top-content-item">
<span class="box1-top-content-item-title">· 涉及领域:</span>
<div
class="box1-top-content-item-tags"
v-for="(domainItem, index) in item.domains"
:key="index"
>
<div class="box1-top-content-item-tags" v-for="(domainItem, index) in item.domains"
:key="index">
<el-tag :type="getTagType(domainItem)">{{ domainItem }}</el-tag>
</div>
</div>
......@@ -133,18 +110,10 @@
<div class="box1-bottom">
<div class="box1-bottom-title">· 涉及主要实体:</div>
<div class="box1-bottom-content">
<div
class="box1-bottom-content-item"
v-for="(ett, index) in item.sanEntities"
:key="index"
@click="handleEntityClick(ett)"
>
<el-image
v-if="ett.img"
class="box1-bottom-content-item-img"
:src="ett.img"
alt=""
></el-image>
<div class="box1-bottom-content-item" v-for="(ett, index) in item.sanEntities" :key="index"
@click="handleEntityClick(ett)">
<el-image v-if="ett.img" class="box1-bottom-content-item-img" :src="ett.img"
alt=""></el-image>
<div v-else class="box1-bottom-content-item-imgUndefined">
{{
(ett.entityNameZh || ett.enName)?.match(
......@@ -217,14 +186,8 @@
</div>
</template>
</custom-container> -->
<RiskSignal
:list="warningList"
@item-click="handleToRiskSignalDetail"
@more-click="handleToMoreRiskSignal"
riskLevel="signalLevel"
postDate="signalTime"
name="signalTitle"
/>
<RiskSignal :list="warningList" @item-click="handleToRiskSignalDetail" @more-click="handleToMoreRiskSignal"
riskLevel="signalLevel" postDate="signalTime" name="signalTitle" />
</el-col>
</el-row>
......@@ -247,19 +210,11 @@
</custom-container>
</el-col> -->
<div class="center-center">
<NewsList
:newsList="newsList"
@item-click="handleNewsInfoClick"
@more-click="handleToMoreNews"
content="newsContent"
/>
<MessageBubble
:messageList="socialMediaList"
@person-click="handlePerClick"
imageUrl="avatar"
@more-click="handleToSocialDetail"
/>
<NewsList :newsList="newsList" @item-click="handleNewsInfoClick" @more-click="handleToMoreNews"
content="newsContent" />
<MessageBubble :messageList="socialMediaList" @person-click="handlePerClick" imageUrl="avatar"
@more-click="handleToSocialDetail" />
<!-- <custom-container title="社交媒体" :titleIcon="dialogIcon" height="450px">
<template #default>
<div class="dialog-list">
......@@ -285,19 +240,14 @@
<template #default="scope">
<div style="display: flex; align-items: center">
<span style="margin-right: 10px; width: 40px">{{ scope.row.num }}</span>
<el-progress
:percentage="scope.row.percent * 100"
:show-text="false"
:status="getStatus(scope.row.percent)"
/>
<el-progress :percentage="scope.row.percent * 100" :show-text="false"
:status="getStatus(scope.row.percent)" />
</div>
</template>
</el-table-column>
<el-table-column label="重点领域" width="220" align="center">
<template #default="scope">
<div
style="display: flex; justify-content: center; align-items: center; gap: 5px"
>
<div style="display: flex; justify-content: center; align-items: center; gap: 5px">
<el-tag v-for="tag in scope.row.tags" :key="tag" :type="getTagType(tag)">{{
tag
}}</el-tag>
......@@ -314,19 +264,14 @@
<template #default="scope">
<div style="display: flex; align-items: center">
<span style="margin-right: 10px; width: 40px">{{ scope.row.num }}</span>
<el-progress
:percentage="scope.row.percent * 100"
:show-text="false"
:status="getStatus(scope.row.percent)"
/>
<el-progress :percentage="scope.row.percent * 100" :show-text="false"
:status="getStatus(scope.row.percent)" />
</div>
</template>
</el-table-column>
<el-table-column label="重点领域" width="220" align="center">
<template #default="scope">
<div
style="display: flex; justify-content: center; align-items: center; gap: 5px"
>
<div style="display: flex; justify-content: center; align-items: center; gap: 5px">
<el-tag v-for="tag in scope.row.tags" :key="tag" :type="getTagType(tag)">{{
tag
}}</el-tag>
......@@ -343,11 +288,8 @@
<template #default="scope">
<div style="display: flex; align-items: center">
<span style="margin-right: 10px; width: 40px">{{ scope.row.num }}</span>
<el-progress
:percentage="scope.row.percent * 100"
:show-text="false"
:status="getStatus(scope.row.percent)"
/>
<el-progress :percentage="scope.row.percent * 100" :show-text="false"
:status="getStatus(scope.row.percent)" />
</div>
</template>
</el-table-column>
......@@ -399,13 +341,9 @@
<el-row :gutter="20" style="width: 1600px; margin: 0 auto; margin-top: 39px">
<CustomTitle id="position4" title="资源库" style="margin-top: 0px" />
<div class="resource-tabs">
<div
v-for="tab in resourceTabs"
:key="tab.value"
class="resource-tab-item"
<div v-for="tab in resourceTabs" :key="tab.value" class="resource-tab-item"
:class="{ active: activeResourceTab === tab.value, disabled: tab.disabled }"
@click="handleResourceTabClick(tab)"
>
@click="handleResourceTabClick(tab)">
{{ tab.label }}
</div>
</div>
......@@ -418,25 +356,15 @@
<div class="box4-item" v-for="(item, idx) in sanctionProcessList" :key="item.title">
<div class="box4-item-left">
<el-image :src="dotIcon" alt="图片" class="box4-item-left-icon" />
<div
class="box4-item-left-line"
v-if="idx + 1 != sanctionProcessList.length"
></div>
<div class="box4-item-left-line" v-if="idx + 1 != sanctionProcessList.length"></div>
</div>
<div class="box4-item-right">
<div class="box4-item-right-header" @click="handleSanc(item)">
<span class="box4-item-right-header-title"
>{{ item.postDate }}{{ item.title }}</span
>
<span class="box4-item-right-header-title">{{ item.postDate }}{{ item.title }}</span>
<span class="box4-item-right-header-desc">{{ item.desc }}</span>
</div>
<el-tooltip
effect="dark"
:content="item.content"
popper-class="common-prompt-popper"
placement="top"
:show-after="500"
>
<el-tooltip effect="dark" :content="item.content" popper-class="common-prompt-popper"
placement="top" :show-after="500">
<div class="box4-item-right-content">
{{ item.content }}
</div>
......@@ -444,12 +372,8 @@
</div>
</div>
</div>
<div
class="box4-footer"
:style="{ marginTop: sanctionProcessList.length > 0 ? '0px' : 'auto' }"
>
<el-button type="primary" link @click="handleGetMore"
>查看更多
<div class="box4-footer" :style="{ marginTop: sanctionProcessList.length > 0 ? '0px' : 'auto' }">
<el-button type="primary" link @click="handleGetMore">查看更多
<el-icon>
<DArrowRight />
</el-icon>
......@@ -466,15 +390,8 @@
</template>
<template #default>
<div class="box5">
<el-table
:data="entitiesList"
class="sanction-table"
stripe
empty-text="暂无数据"
height="700px"
header-row-class-name="table-header"
row-class-name="table-row"
>
<el-table :data="entitiesList" class="sanction-table" stripe empty-text="暂无数据" height="700px"
header-row-class-name="table-header" row-class-name="table-row">
<!-- <el-table-column prop="index" label="序号" width="80" align="center">
<template #default="scope">
{{ scope.$index + 1 + (currentPage - 1) * pageSize }}
......@@ -484,12 +401,8 @@
<el-table-column prop="name" label="实体名称" min-width="200">
<template #default="scope">
<div class="tableName" @click="handleCompClick(scope.row)">
<el-image
v-if="scope.row.img"
class="box1-bottom-content-item-img"
:src="scope.row.img"
alt=""
></el-image>
<el-image v-if="scope.row.img" class="box1-bottom-content-item-img" :src="scope.row.img"
alt=""></el-image>
<div v-else class="box1-bottom-content-item-imgUndefined">
{{
(scope.row.name || scope.row.enName)?.match(
......@@ -540,19 +453,13 @@
<el-table-column prop="revenue" label="50%规则子企业" width="280" align="right">
<template #default="scope">
<div class="num-item" v-if="scope.row.ruleOrgCount > 0">
<div
class="name-item"
:class="[
'revenue-cell',
scope.row.revenue === '无营收数据' ? 'no-revenue' : ''
]"
>
<div class="name-item" :class="[
'revenue-cell',
scope.row.revenue === '无营收数据' ? 'no-revenue' : ''
]">
{{ scope.row.ruleOrgList[0].orgName }}...等
</div>
<div
style="width: 50px; color: #409eff; cursor: pointer"
@click="handleOrgClick(scope.row)"
>
<div style="width: 50px; color: #409eff; cursor: pointer" @click="handleOrgClick(scope.row)">
{{ scope.row.ruleOrgCount }}家>
</div>
</div>
......@@ -564,15 +471,8 @@
<!-- <div class="pagination-info">
第{{ currentPage }}页,共{{ totalPages }}页
</div> -->
<el-pagination
v-model:current-page="currentPage"
:page-size="pageSize"
:total="total"
:pager-count="5"
layout="prev, pager, next"
background
@current-change="handlePageChange"
/>
<el-pagination v-model:current-page="currentPage" :page-size="pageSize" :total="total"
:pager-count="5" layout="prev, pager, next" background @current-change="handlePageChange" />
</div>
</div>
</template>
......@@ -638,14 +538,8 @@
</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"
/>
<el-pagination v-model:current-page="currentPageAll" :page-size="pageSizeAll" :total="totalAll"
layout="prev, pager, next" background @current-change="handlePageChangeAll" />
</div>
</div>
</div>
......@@ -680,12 +574,8 @@
</div>
</template>
</el-dialog> -->
<RuleSubsidiaryDialog
v-model="dialogVisible"
:company-name="currentRuleCompany"
:total-count="currentRuleCount"
:data-list="currentOrgList"
/>
<RuleSubsidiaryDialog v-model="dialogVisible" :company-name="currentRuleCompany" :total-count="currentRuleCount"
:data-list="currentOrgList" />
</div>
<el-dialog v-model="mediaVisible" title="社交媒体信息" width="500" :before-close="handleMediaClose">
<div class="dialog-content">
......@@ -701,7 +591,7 @@
</template>
<script setup>
import NewsList from "@/components/NewsList.vue";
import NewsList from "@/components/base/newsList/index.vue";
import RiskSignal from "@/components/base/RiskSignal/index.vue";
import { onMounted, ref, computed, reactive, shallowRef, watch, nextTick } from "vue";
import { useContainerScroll } from "@/hooks/useScrollShow";
......@@ -1370,7 +1260,7 @@ const fetchSanctionList = async () => {
});
totalAll.value = res.totalElements;
}
} catch (error) {}
} catch (error) { }
};
const handlePageChangeAll = val => {
......@@ -1642,7 +1532,7 @@ const handleGetHylyList = async () => {
hylymc: "全部分类"
};
categoryList.value = [obj, ...categoryList.value];
} catch (error) {}
} catch (error) { }
};
const chart1Data = ref({
......@@ -2118,6 +2008,7 @@ const handleMediaClick = item => {
// align-items: flex-start;
gap: 100px;
flex: 1;
.box3-content {
display: flex;
flex-direction: column;
......@@ -2141,6 +2032,7 @@ const handleMediaClick = item => {
}
.box3-content {
// flex: 1;
.el-progress--line {
width: 82px;
......@@ -3535,7 +3427,6 @@ const handleMediaClick = item => {
height: 450px;
display: flex;
gap: 20px;
.center-center-news {
flex-shrink: 0;
}
......
......@@ -12,13 +12,8 @@
<div class="home-top-bg"></div>
<div class="home-main-header">
<div class="home-main-header-center">
<SearchContainer
style="margin-bottom: 0; height: fit-content"
v-if="containerRef"
placeholder="搜索投融资限制政策"
:containerRef="containerRef"
areaName=""
/>
<SearchContainer style="margin-bottom: 0; height: fit-content" v-if="containerRef" placeholder="搜索投融资限制政策"
:containerRef="containerRef" areaName="" />
<!-- <el-input
v-model="searchKey"
style="width: 100%; height: 48px"
......@@ -115,17 +110,9 @@
</div>
<div class="box1-top-content-item">
<span class="box1-top-content-item-title">· 涉及领域:</span>
<div
class="box1-top-content-item-tags"
v-for="item in ['航空航天', '人工智能', '集成电路']"
:key="item"
>
<el-tag
:type="
item === '航空航天' ? 'primary' : item === '人工智能' ? 'danger' : 'info'
"
>{{ item }}</el-tag
>
<div class="box1-top-content-item-tags" v-for="item in ['航空航天', '人工智能', '集成电路']" :key="item">
<el-tag :type="item === '航空航天' ? 'primary' : item === '人工智能' ? 'danger' : 'info'
">{{ item }}</el-tag>
</div>
</div>
</div>
......@@ -183,14 +170,8 @@
</template>
</custom-container> -->
<RiskSignal
:list="warningList"
@item-click="handleToRiskSignalDetail"
@more-click="handleToMoreRiskSignal"
riskLevel="status"
postDate="time"
name="title"
/>
<RiskSignal :list="warningList" @item-click="handleToRiskSignalDetail" @more-click="handleToMoreRiskSignal"
riskLevel="status" postDate="time" name="title" />
</el-col>
</el-row>
<el-row :gutter="20" style="width: 1600px; margin: 0 auto">
......@@ -214,22 +195,11 @@
<div class="center-center">
<div class="center-center-news">
<NewsList
:newsList="customNewsData"
@item-click="handleNewsInfoClick"
@more-click="handleToMoreNews"
from="from"
content="description"
title="title"
img="image"
/>
<NewsList :newsList="customNewsData" @item-click="handleNewsInfoClick" @more-click="handleToMoreNews"
from="from" content="description" title="title" img="image" />
</div>
<MessageBubble
:messageList="messageList"
@person-click="handlePerClick"
imageUrl="avatar"
@more-click="handleToSocialDetail"
/>
<MessageBubble :messageList="messageList" @person-click="handlePerClick" imageUrl="avatar"
@more-click="handleToSocialDetail" />
<!-- <div class="boxs4">
<custom-container title="社交媒体" :titleIcon="dialogIcon" height="450px">
<template #default>
......@@ -269,27 +239,18 @@
<template #default="scope">
<div style="display: flex; align-items: center">
<span style="margin-right: 10px; width: 40px">{{ scope.row.num }}</span>
<el-progress
:percentage="scope.row.percent * 100"
:show-text="false"
:status="getStatus(scope.row.percent)"
/>
<el-progress :percentage="scope.row.percent * 100" :show-text="false"
:status="getStatus(scope.row.percent)" />
</div>
</template>
</el-table-column>
<el-table-column label="重点领域" width="180">
<template #default="scope">
<div style="display: flex; align-items: center; gap: 5px">
<el-tag
v-for="tag in scope.row.tags"
:key="tag"
:type="
tag === '通信网络'
? 'primary'
: TAGTYPE[Math.floor(Math.random() * 5)]
"
>{{ tag }}</el-tag
>
<el-tag v-for="tag in scope.row.tags" :key="tag" :type="tag === '通信网络'
? 'primary'
: TAGTYPE[Math.floor(Math.random() * 5)]
">{{ tag }}</el-tag>
</div>
</template>
</el-table-column>
......@@ -303,27 +264,18 @@
<template #default="scope">
<div style="display: flex; align-items: center">
<span style="margin-right: 10px; width: 40px">{{ scope.row.num }}</span>
<el-progress
:percentage="scope.row.percent * 100"
:show-text="false"
:status="getStatus(scope.row.percent)"
/>
<el-progress :percentage="scope.row.percent * 100" :show-text="false"
:status="getStatus(scope.row.percent)" />
</div>
</template>
</el-table-column>
<el-table-column label="重点领域" width="180">
<template #default="scope">
<div style="display: flex; align-items: center; gap: 5px">
<el-tag
v-for="tag in scope.row.tags"
:key="tag"
:type="
tag === '通信网络'
? 'primary'
: TAGTYPE[Math.floor(Math.random() * 5)]
"
>{{ tag }}</el-tag
>
<el-tag v-for="tag in scope.row.tags" :key="tag" :type="tag === '通信网络'
? 'primary'
: TAGTYPE[Math.floor(Math.random() * 5)]
">{{ tag }}</el-tag>
</div>
</template>
</el-table-column>
......@@ -337,27 +289,18 @@
<template #default="scope">
<div style="display: flex; align-items: center">
<span style="margin-right: 10px; width: 40px">{{ scope.row.num }}</span>
<el-progress
:percentage="scope.row.percent * 100"
:show-text="false"
:status="getStatus(scope.row.percent)"
/>
<el-progress :percentage="scope.row.percent * 100" :show-text="false"
:status="getStatus(scope.row.percent)" />
</div>
</template>
</el-table-column>
<el-table-column label="重点领域" width="180">
<template #default="scope">
<div style="display: flex; align-items: center; gap: 5px">
<el-tag
v-for="tag in scope.row.tags"
:key="tag"
:type="
tag === '通信网络'
? 'primary'
: TAGTYPE[Math.floor(Math.random() * 5)]
"
>{{ tag }}</el-tag
>
<el-tag v-for="tag in scope.row.tags" :key="tag" :type="tag === '通信网络'
? 'primary'
: TAGTYPE[Math.floor(Math.random() * 5)]
">{{ tag }}</el-tag>
</div>
</template>
</el-table-column>
......@@ -414,8 +357,7 @@
</div>
</div>
<div class="box4-footer">
<el-button type="primary" link :icon="DownRight"
>查看更多
<el-button type="primary" link :icon="DownRight">查看更多
<el-icon>
<DArrowRight />
</el-icon>
......@@ -432,15 +374,8 @@
</template>
<template #default>
<div class="box5">
<el-table
:data="paginatedData"
class="sanction-table"
stripe
empty-text="暂无数据"
height="700px"
header-row-class-name="table-header"
row-class-name="table-row"
>
<el-table :data="paginatedData" class="sanction-table" stripe empty-text="暂无数据" height="700px"
header-row-class-name="table-header" row-class-name="table-row">
<!-- <el-table-column prop="index" label="序号" width="80" align="center">
<template #default="scope">
{{ scope.$index + 1 + (currentPage - 1) * pageSize }}
......@@ -449,14 +384,12 @@
<el-table-column prop="name" label="实体名称" min-width="200">
<template #default="scope">
<div
style="
<div style="
font-weight: 700;
font-size: 16px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
"
>
">
{{ scope.row.name }}
</div>
</template>
......@@ -465,12 +398,8 @@
<el-table-column prop="domains" label="涉及领域" min-width="180">
<template #default="scope">
<div class="domain-tags">
<el-tag
v-for="tag in scope.row.domains"
:key="tag"
:type="tag === '通信网络' ? 'primary' : 'danger'"
>{{ tag }}</el-tag
>
<el-tag v-for="tag in scope.row.domains" :key="tag"
:type="tag === '通信网络' ? 'primary' : 'danger'">{{ tag }}</el-tag>
</div>
</template>
</el-table-column>
......@@ -506,9 +435,7 @@
<el-table-column prop="revenue" label="50%规则子企业" width="140" align="right">
<template #default="scope">
<span
:class="['revenue-cell', scope.row.revenue === '无营收数据' ? 'no-revenue' : '']"
>
<span :class="['revenue-cell', scope.row.revenue === '无营收数据' ? 'no-revenue' : '']">
{{ scope.row.revenue }}
</span>
</template>
......@@ -519,14 +446,8 @@
<!-- <div class="pagination-info">
第{{ currentPage }}页,共{{ totalPages }}页
</div> -->
<el-pagination
v-model:current-page="currentPage"
:page-size="pageSize"
:total="total"
:pager-count="5"
layout="prev, pager, next"
background
/>
<el-pagination v-model:current-page="currentPage" :page-size="pageSize" :total="total"
:pager-count="5" layout="prev, pager, next" background />
</div>
</div>
</template>
......@@ -555,7 +476,7 @@ import CustomContainer from "@/components/Container/index.vue";
import ClickableCard from "./components/link.vue";
import InfoCard from "./components/info.vue";
import CustomTitle from "./components/title.vue";
import NewsList from "@/components/NewsList.vue";
import NewsList from "@/components/base/newsList/index.vue";
import trumpAvatar from "@/assets/images/icon-trump.png";
import elongAvatar from "@/assets/images/icon-elong.png";
......@@ -1297,7 +1218,7 @@ const handleGetHylyList = async () => {
hylymc: "全部分类"
};
categoryList.value = [obj, ...categoryList.value];
} catch (error) {}
} catch (error) { }
};
const chart1Data = ref({
......@@ -1343,7 +1264,7 @@ const handleGetBillsByType = async () => {
img: bill1
};
});
} catch (error) {}
} catch (error) { }
};
// 查看社交媒体详情
const handleToSocialDetail = item => {
......
......@@ -311,7 +311,7 @@
<script setup>
import RiskSignal from "@/components/RiskSignal/RiskSignal.vue";
import RiskSignal from "@/components/base/riskSignal/index.vue";
import NewsList from "@/components/base/newsList/index.vue";
import { onMounted, ref, computed } from "vue";
import * as echarts from "echarts";
......
......@@ -61,7 +61,7 @@
</template>
<script setup>
import NewsList from "@/components/NewsList.vue";
import NewsList from "@/components/base/newsList/index.vue";
import { ref, onBeforeMount } from "vue";
import router from "@/router"
......
......@@ -3,13 +3,8 @@
<div class="main-content" ref="homeMainRef">
<div class="home-top-bg"></div>
<!-- 搜索栏部分 -->
<SearchContainer
v-if="homeMainRef"
:countInfo="statCountInfo"
placeholder="搜索规则限制"
:containerRef="homeMainRef"
areaName=""
/>
<SearchContainer v-if="homeMainRef" :countInfo="statCountInfo" placeholder="搜索规则限制" :containerRef="homeMainRef"
areaName="" />
<!-- 最新动态 -->
<div class="newdata" id="position1">
<com-title title="最新动态" />
......
......@@ -215,9 +215,11 @@ onMounted(async () => {
margin: 0;
padding: 0;
}
.coop-page {
width: 100%;
height: 100%;
// .breadcrumb {
// width: 100%;
// height: 64px;
......@@ -245,6 +247,7 @@ onMounted(async () => {
width: 960px;
height: 168px;
margin: 0 auto 68px auto;
.search-center {
width: 688px;
height: 48px;
......@@ -284,6 +287,7 @@ onMounted(async () => {
}
}
}
.search-main {
display: flex;
padding-right: 3px;
......@@ -295,9 +299,11 @@ onMounted(async () => {
background-color: rgba(255, 255, 255, 0.65);
border-radius: 10px;
border: 1px solid #fff;
&:hover {
border: 1px solid var(--color-main-active);
}
.search-input {
border: none;
outline: none;
......@@ -315,6 +321,7 @@ onMounted(async () => {
color: #a8abb2;
}
}
.search-btn {
cursor: pointer;
display: flex;
......@@ -330,6 +337,7 @@ onMounted(async () => {
font-family: "Microsoft YaHei";
line-height: 22px;
color: #fff;
img {
width: 18px;
height: 18px;
......@@ -337,6 +345,7 @@ onMounted(async () => {
}
}
}
.search-bottom {
width: 688px;
height: 48px;
......@@ -344,6 +353,7 @@ onMounted(async () => {
margin-top: 36px;
display: flex;
justify-content: space-between;
// gap: 16px;
.btn {
display: flex;
......@@ -357,9 +367,11 @@ onMounted(async () => {
background: #e7f3ff;
cursor: pointer;
position: relative;
&:hover {
background: #cae3fc;
}
.btn-text {
width: 80px;
color: var(--color-main-active);
......@@ -370,12 +382,14 @@ onMounted(async () => {
margin-left: 36px;
text-align: center;
}
.btn-icon {
position: absolute;
top: 16px;
right: 19px;
width: 6px;
height: 12px;
img {
width: 100%;
height: 100%;
......@@ -384,40 +398,48 @@ onMounted(async () => {
}
}
}
.newdata {
width: 1600px;
height: 538px;
margin: 36px auto 64px auto;
.newdata-main {
width: 1600px;
height: 460px;
margin-top: 36px;
}
}
.ask {
width: 1600px;
height: 528px;
margin: 0 auto 64px auto;
.ask-main {
width: 1600px;
height: 450px;
margin-top: 36px;
}
}
.datasub {
width: 1600px;
height: 538px;
margin: 0 auto 88px auto;
.datasub-main {
width: 1600px;
height: 460px;
margin-top: 36px;
}
}
.reslib {
width: 1600px;
height: 1633px;
margin: 0 auto 0px auto;
.reslib-main {
width: 1600px;
height: 1565px;
......@@ -486,6 +508,7 @@ onMounted(async () => {
.search-icon {
width: 18px;
height: 18px;
img {
width: 100%;
height: 100%;
......@@ -522,9 +545,11 @@ onMounted(async () => {
background: #e7f3ff;
cursor: pointer;
position: relative;
&:hover {
background: #cae3fc;
}
.btn-text {
width: 80px;
color: var(--color-main-active);
......@@ -535,12 +560,14 @@ onMounted(async () => {
margin-left: 36px;
text-align: center;
}
.btn-icon {
position: absolute;
top: 16px;
right: 19px;
width: 6px;
height: 12px;
img {
width: 100%;
height: 100%;
......
......@@ -53,7 +53,7 @@
</template>
<script setup>
import NewsList from "@/components/NewsList.vue";
import NewsList from "@/components/base/newsList/index.vue";
import { ref, onMounted } from "vue";
import {
......
......@@ -19,7 +19,10 @@
</div>
</div>
<div class="header-top-right">
<div class="name">{{ thinkInfo.thinkTankName }}</div>
<div class="image-name-box">
<div class="image"> <img :src=thinkInfo.thinkTankLogoUrl alt="" /></div>
<div class="name">{{ thinkInfo.thinkTankName }}</div>
</div>
<div class="time">{{ thinkInfo.times }}</div>
</div>
</div>
......@@ -47,6 +50,12 @@
</div>
<div class="text">{{ "查看官网" }}</div>
</div> -->
<div class="btn">
<div class="icon">
<img src="./images/btn-icon2.png" alt="" />
</div>
<div class="text" @click="goToOfficialWebsite()">{{ "查看官网" }}</div>
</div>
<div class="btn">
<div class="icon">
<img src="./images/btn-icon2.png" alt="" />
......@@ -69,7 +78,7 @@
</div>
</div>
<div class="main">
<ReportAnalysis v-if="tabActiveName === '报告分析'"></ReportAnalysis>
<ReportAnalysis v-if="tabActiveName === '报告分析'" :thinkInfo="thinkInfo" :reportList="reportList"></ReportAnalysis>
<PolicyTracking v-else></PolicyTracking>
</div>
</div>
......@@ -80,12 +89,13 @@ import { ref, onMounted } from "vue";
import ReportAnalysis from "./reportAnalysis/index.vue";
import PolicyTracking from "./policyTracking/index.vue";
import { getThinkTankReportSummary } from "@/api/thinkTank/overview";
import { getThinkTankReportSummary, getThinkTankReportRelated } from "@/api/thinkTank/overview";
import { useRoute, useRouter } from "vue-router";
const router = useRouter();
const route = useRoute();
const reportUrl = ref("");
const thinkInfo = ref({});
const reportList = ref({})
// 获取报告全局信息
const handleGetThinkTankReportSummary = async () => {
......@@ -101,7 +111,20 @@ const handleGetThinkTankReportSummary = async () => {
console.error("获取报告全局信息error", error);
}
};
// 获取相关报告信息
const handleGetThinkTankReport = async () => {
try {
const res = await getThinkTankReportRelated(router.currentRoute._value.params.id);
console.log("报告全局信息", res);
if (res.code === 200 && res.data) {
reportList.value = res.data;
}
} catch (error) {
console.error("获取相关报告error", error);
}
};
const toReport = () => {
console.log(reportUrl.value, "reportUrl.valuereportUrl.value");
const route = router.resolve({
......@@ -129,7 +152,17 @@ const handleAnalysisClick = () => {
};
onMounted(async () => {
handleGetThinkTankReportSummary();
handleGetThinkTankReport();
});
const goToOfficialWebsite = () => {
const url = thinkInfo.value?.reportUrl;
if (!url) {
return;
}
// 简单校验一下,防止空字符串
window.open(url, "_blank");
};
</script>
<style lang="scss" scoped>
......@@ -199,15 +232,46 @@ onMounted(async () => {
}
.header-top-right {
.name {
display: flex;
flex-direction: column;
text-align: right;
align-items: flex-end;
.image-name-box {
width: 118px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
gap: 6px;
text-align: right;
display: flex;
justify-content: flex-end;
.name {
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: right;
}
.image {
width: 16px;
height: 16px;
margin-top: 5px;
img {
width: 100%;
height: 100%;
}
}
}
.time {
......
......@@ -17,9 +17,39 @@
<div class="box1-main">
{{ box1Data }}
</div> -->
<AnalysisBox title="内容摘要" :showAllBtn="false">
<AnalysisBox title="基本信息" :showAllBtn="true">
<div class="box1-main">
{{ box1Data }}
<div class="text-box">
<div class="time">
<div class="time-title">发布时间:</div>
<div class="time-content">{{ publishTime }}</div>
</div>
<div class="topic">
<div class="topic-title">报告主题:</div>
<div class="topic-content">{{ reportTopic }}</div>
</div>
<div class="author">
<div class="author-title">报告作者:</div>
<div class="author-content">
<template v-if="Array.isArray(reportAuthors) && reportAuthors.length">
<span v-for="(author, idx) in reportAuthors" :key="idx">
{{ author.name }}
<span v-if="idx < reportAuthors.length - 1"></span>
</span>
</template>
</div>
</div>
</div>
<div class="author-box" v-for="(author, idx) in reportAuthors" :key="idx"
v-if="Array.isArray(reportAuthors) && reportAuthors.length">
<div class="author-item">
<div class="image"><img :src="author.avatar" :alt="reportAuthors[0].name" /></div>
<div class="author-text">
<div class="author-name">{{ author.name }}</div>
<div class="author-position">{{ author.job }}</div>
</div>
</div>
</div>
</div>
</AnalysisBox>
</div>
......@@ -39,31 +69,65 @@
<div class="box2-main">
<div class="box2-content" id="box2Chart"></div>
</div> -->
<AnalysisBox title="关键词云" :showAllBtn="false">
<AnalysisBox title="相关报告" :showAllBtn="true">
<div class="box2-main">
<div class="box2-content" id="box2Chart"></div>
<div class="box2-item" v-for="(report, idx) in reportList" :key="idx">
<div class="box2-item-content">
<div class="left"><img :src="report.image" alt="" /></div>
<div class="right-content">
<div class="report-title">{{ report.name }}</div>
<div class="report-footer">
<div class="report-time">{{ report.postDate }}</div>
<div class="report-footer-right">
<div class="footer-image">
<img :src="report.thinktankLogo" alt="" />
</div>
<div class="think-name">{{ report.thinktankName }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="box2-btn">
<div class="btn-text">
多智库报告观点汇聚分析
</div>
<div class="btn-image">
<img src="../images/btn-right.png" alt="">
</div>
</div>
</AnalysisBox>
</div>
</div>
<div class="right">
<div class="box3">
<AnalysisBox title="主要观点" :showAllBtn="false">
<AnalysisBox title="报告摘要" :showAllBtn="true">
<div class="box3-main">
<div class="box3-main-main">
<div class="box3-item" v-for="(item, index) in majorOpinions" :key="index">
<div class="box3-top">
<div class="top-title">
<div class="title-image">
<img src="../images/title-image.png" alt="" />
</div>
</div>
</div>
<div class="box3-text"> {{ box1Data }}</div>
</div>
</AnalysisBox>
</div>
<div class="box4">
<AnalysisBox title="核心论点" :showAllBtn="true">
<div class="box4-main">
<div class="box4-main-main">
<div class="box4-item" v-for="(item, index) in majorOpinions" :key="index">
<div class="left">
{{ index + 1 }}
</div>
<div class="center">
<div class="title">{{ item.content }}</div>
<div>
<img
src="../images/image-open.png"
alt=""
class="center-image"
@click="handleOpenReportOriginal(item)"
/>
<img src="../images/image-open.png" alt="" class="center-image"
@click="handleOpenReportOriginal(item)" />
</div>
<!-- <div class="desc">{{ item.econtent }}</div> -->
</div>
......@@ -81,17 +145,11 @@
</div> -->
</div>
</div>
<div class="box3-main-footer">
<div class="box4-main-footer">
<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"
/>
<el-pagination :page-size="12" background layout="prev, pager, next" :total="total"
@current-change="handleCurrentChange" :current-page="currentPage" />
</div>
</div>
</div>
......@@ -102,7 +160,7 @@
</template>
<script setup>
import { ref, onMounted } from "vue";
import { ref, onMounted, computed, defineProps } from "vue";
import setChart from "@/utils/setChart";
import getWordCloudChart from "./utils/worldCloudChart";
import {
......@@ -116,6 +174,41 @@ import { useRouter } from "vue-router";
const router = useRouter();
import "echarts-wordcloud";
const props = defineProps({
thinkInfo: {
type: Object,
default: () => ({})
},
reportList: {
type: Object,
default: () => ({})
}
});
const publishTime = computed(() => {
const info = props.thinkInfo || {};
// 优先用 times,其次用 reportTime 的日期部分
if (info.times) return info.times;
if (info.reportTime && typeof info.reportTime === "string") {
return info.reportTime.split("T")[0];
}
return "";
});
const reportTopic = computed(() => {
const info = props.thinkInfo || {};
return info.summary;
});
const reportAuthors = computed(() => {
const info = props.thinkInfo || {};
if (Array.isArray(info.authors) && info.authors.length) {
return info.authors;
}
return [];
});
// 内容摘要
const box1Data =
ref(`包括经济竞争在内的美中竞争自2017年以来一直在定义美国外交政策。这两个经济体是世界上第一和第二大国家经济体,并且深深交织在一起。改变关系,无论多么必要,可能是昂贵的。因此,美国面临着一项挑战,确保其经济在耦合的战略竞争条件下满足国家的需求。
......@@ -391,122 +484,321 @@ onMounted(() => {
}
.left {
gap: 16px;
display: flex;
flex-direction: column;
.box1 {
margin-top: 17px;
width: 480px;
height: 390px;
height: 486px;
// border: 1px solid rgba(234, 236, 238, 1);
// border-radius: 10px;
// box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
// background: rgba(255, 255, 255, 1);
.box1-main {
margin: 5px auto;
width: 428px;
height: 315px;
/* 9行 * 30px/行 = 270px,这里可以稍微调整 */
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
overflow-y: auto;
// display: -webkit-box;
// /* 使用Webkit的弹性盒模型 */
// -webkit-box-orient: vertical;
// /* 垂直排列 */
// -webkit-line-clamp: 9;
// /* 限制显示9行 */
// overflow: hidden;
// /* 隐藏超出部分 */
}
width: 480px;
height: 438px;
.box1-footer {
margin: 0 auto;
width: 108px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
cursor: pointer;
.text-box {
width: 437px;
&:hover {
background: var(--color-bg-hover);
}
margin-left: 22px;
margin-top: 8px;
gap: 12px;
display: flex;
flex-direction: column;
.text {
height: 22px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
.time {
height: 24px;
display: flex;
gap: 4px;
.time-title {
width: 88px;
font-family: "Source Han Sans CN";
font-weight: 700;
font-size: 16px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
color: rgb(59, 65, 75);
}
.time-content {
width: 345px;
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 16px;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
color: rgb(59, 65, 75);
}
}
.topic {
display: flex;
gap: 4px;
.topic-title {
width: 88px;
font-family: "Source Han Sans CN";
font-weight: 700;
font-size: 16px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
color: rgb(59, 65, 75);
}
.topic-content {
width: 345px;
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 16px;
line-height: 30px;
letter-spacing: 0px;
text-align: left;
color: rgb(59, 65, 75);
}
}
.author {
height: 24px;
display: flex;
gap: 4px;
.author-title {
width: 88px;
font-family: "Source Han Sans CN";
font-weight: 700;
font-size: 16px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
color: rgb(59, 65, 75);
}
.author-content {
width: 345px;
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 16px;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
color: rgb(59, 65, 75);
}
}
}
.icon {
width: 16px;
height: 16px;
.author-box {
width: 437px;
height: 220px;
margin-top: 34px;
margin-left: 18px;
.author-item {
width: 213px;
height: 49px;
display: flex;
gap: 11px;
.image {
width: 42px;
height: 42px;
margin-top: 3px;
margin-left: 3px;
display: inline-block;
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.author-text {
width: 154px;
height: 49px;
.author-name {
width: 154px;
height: 24px;
font-family: "Source Han Sans CN";
font-weight: 700;
font-size: 16px;
line-height: 24px;
letter-spacing: 0;
text-align: left;
color: rgb(59, 65, 75);
}
.author-position {
width: 154px;
height: 22px;
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 14px;
line-height: 22px;
letter-spacing: 0;
text-align: left;
color: rgb(95, 101, 108);
}
}
img {
width: 100%;
height: 100%;
}
}
}
}
.box2 {
margin-top: 16px;
width: 480px;
height: 390px;
height: 648px;
// border: 1px solid rgba(234, 236, 238, 1);
// border-radius: 10px;
// box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
// background: rgba(255, 255, 255, 1);
.box2-main {
width: 430px;
height: 320px;
margin: 10px auto;
width: 436px;
margin-top: 5px;
margin-left: 23px;
.box2-main-tag-box {
display: flex;
flex-wrap: wrap;
height: 89px;
box-sizing: border-box;
padding: 8px 0;
gap: 8px;
.tag {
height: 28px;
line-height: 28px;
padding: 0 8px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(255, 255, 255, 1);
cursor: pointer;
}
.box2-item {
height: 103px;
width: 100%;
border-bottom: 1px solid rgba(234, 236, 238, 1);
border-top: 1px solid rgba(234, 236, 238, 1);
.box2-item-content {
width: 100%;
height: 90px;
margin-top: 7px;
display: flex;
.left {
width: 56px;
height: 74px;
margin-top: 8px;
img {
width: 100%;
height: 100%;
}
}
.tagActive {
color: var(--color-main-active);
border: 1px solid var(--color-main-active);
background: rgba(231, 243, 255, 1);
.right-content {
margin-left: 13px;
width: 365px;
height: 76px;
margin-top: 7px;
.report-title {
height: 48px;
font-family: "Source Han Sans CN";
font-weight: 700;
font-size: 16px;
line-height: 24px;
letter-spacing: 0;
text-align: left;
}
.report-footer {
margin-top: 4px;
height: 22px;
justify-content: space-between;
display: flex;
.report-time {
height: 22px;
width: 97px;
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 14px;
line-height: 22px;
letter-spacing: 0;
text-align: left;
color: rgb(95, 101, 108);
}
.report-footer-right {
height: 22px;
display: flex;
gap: 6px;
.footer-image {
width: 16px;
height: 16px;
margin-top: 3px;
img {
width: 100%;
height: 100%;
}
}
.think-name {
height: 22px;
}
}
}
}
}
}
}
.box2-btn {
margin-top: 16px;
margin-left: 23px;
width: 436px;
height: 36px;
background-color: rgb(5, 95, 194);
border-radius: 6px;
display: flex;
.btn-text {
color: rgb(255, 255, 255);
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 16px;
line-height: 22px;
letter-spacing: 0;
margin-left: 120px;
margin-top: 7px;
.box2-content {
width: 430px;
height: 315px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
background: rgba(247, 248, 249, 1);
}
.btn-image {
width: 13px;
height: 8px;
margin-left: 8px;
display: inline-block;
margin-top: 14px;
img {
width: 100%;
height: 100%;
display: block;
}
}
}
}
......@@ -514,8 +806,73 @@ onMounted(() => {
.right {
margin-top: 17px;
gap: 16px;
display: flex;
flex-direction: column;
.box3 {
width: 1103px;
height: 545px;
// border: 1px solid rgba(234, 236, 238, 1);
// border-radius: 10px;
// box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
// background: rgba(255, 255, 255, 1);
.box3-main {
width: 1058px;
height: 466px;
margin-top: 3px;
margin-left: 22px;
.box3-top {
width: 1058px;
height: 48px;
background: linear-gradient(rgb(137, 193, 255, 0.1), rgb(255, 255, 255));
display: flex;
.top-title {
width: 1010px;
height: 32px;
margin-left: 24px;
margin-top: 16px;
.title-image {
width: 199px;
height: 32px;
img {
width: 100%;
height: 100%;
}
}
}
}
.box3-text {
width: 1006px;
margin-top: 24px;
margin-left: 26px;
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 16px;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
text-justify: inter-ideograph;
}
}
}
.box4 {
width: 1103px;
height: 965px;
// border: 1px solid rgba(234, 236, 238, 1);
......@@ -524,16 +881,16 @@ onMounted(() => {
// background: rgba(255, 255, 255, 1);
position: relative;
.box3-main {
.box4-main {
width: 1057px;
margin: 0 auto;
.box3-main-main {
.box4-main-main {
height: 767px;
overflow: hidden;
.box3-item {
.box4-item {
width: 1057px;
height: 72px;
box-sizing: border-box;
......@@ -594,19 +951,7 @@ onMounted(() => {
margin-left: 18px;
}
.desc {
height: 22px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.right {
......@@ -650,14 +995,14 @@ onMounted(() => {
}
}
.box3-item:nth-child(2n-1) {
.box4-item {
border-bottom: 1px solid rgba(234, 236, 238, 1);
border-top: 1px solid rgba(234, 236, 238, 1);
background: rgba(247, 248, 249, 1);
}
}
.box3-main-footer {
.box4-main-footer {
height: 80px;
display: flex;
justify-content: space-between;
......@@ -675,7 +1020,7 @@ onMounted(() => {
}
}
.box3-footer {
.box4-footer {
position: absolute;
left: 22px;
bottom: 19px;
......@@ -725,4 +1070,8 @@ onMounted(() => {
}
}
}
:deep(.analysis-box-wrapper .wrapper-header) {
height: 54px !important;
}
</style>
......@@ -10,18 +10,17 @@
<!-- <div class="box-header-right">{{ "查看数据源 >" }}</div> -->
<div class="select-box">
<el-select v-model="box1SelectYear" placeholder="选择时间" style="width: 100px">
<el-option
v-for="(item, index) in box1YearList"
:key="index"
:label="item.label + '年'"
:value="item.value"
@click="handleGetThinkPolicyIndustry()"
/>
<el-option v-for="(item, index) in box1YearList" :key="index" :label="item.label + '年'"
:value="item.value" @click="handleGetThinkPolicyIndustry()" />
</el-select>
</div>
</div>
<div class="box-main">
<div id="box1Chart"></div>
<div class="source">
<div class="info"><img src="./images/image-exclamation.png"></div>
<div class="text"> 数据来源:美国国会官网,数据时间:2015.1至2025.12</div>
</div>
</div>
</div>
<div class="box1 box">
......@@ -32,19 +31,18 @@
<div class="title">{{ "政策建议涉及部门分布" }}</div>
<!-- <div class="box-header-right">{{ "查看数据源 >" }}</div> -->
<div class="select-box">
<el-select v-model="box1SelectYear" placeholder="选择时间" style="width: 100px">
<el-option
v-for="(item, index) in box1YearList"
:key="index"
:label="item.label + '年'"
:value="item.value"
@click="handleGetThinkPolicyIndustry()"
/>
<el-select v-model="box2SelectYear" placeholder="选择时间" style="width: 100px">
<el-option v-for="(item, index) in box2YearList" :key="index" :label="item.label + '年'"
:value="item.value" @click="handleGetPolicyAdviceDeptDistribution()" />
</el-select>
</div>
</div>
<div class="box-main">
<div id="box2Chart"></div>
<div class="source">
<div class="info"><img src="./images/image-exclamation.png"></div>
<div class="text"> 数据来源:美国国会官网,数据时间:2015.1至2025.12</div>
</div>
</div>
</div>
<!-- <div class="box2 box">
......@@ -83,18 +81,17 @@
<!-- <div class="box-header-right">{{ "查看数据源 >" }}</div> -->
<div class="select-box">
<el-select v-model="box3SelectMonths" placeholder="选择时间" style="width: 100px">
<el-option
v-for="item in box3MonthsList"
:key="item.value"
:label="item.label + '年'"
:value="item.value"
@click="handleGetThinkPolicyIndustryChange()"
/>
<el-option v-for="item in box3MonthsList" :key="item.value" :label="item.label + '年'" :value="item.value"
@click="handleGetThinkPolicyIndustryChange()" />
</el-select>
</div>
</div>
<div class="box-main">
<div class="box3-main">
<div id="box3Chart"></div>
<div class="source">
<div class="info"><img src="./images/image-exclamation.png"></div>
<div class="text"> 数据来源:美国国会官网,数据时间:2015.1至2025.12</div>
</div>
</div>
</div>
</div>
......@@ -111,14 +108,8 @@
<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
class="select-box-sort"
v-model="sort"
placeholder="倒序"
style="width: 120px"
:teleported="true"
:placement="'bottom-start'"
:popper-options="{
<el-select class="select-box-sort" v-model="sort" placeholder="倒序" style="width: 120px" :teleported="true"
:placement="'bottom-start'" :popper-options="{
modifiers: [
{
name: 'preventOverflow',
......@@ -129,8 +120,7 @@
enabled: false
}
]
}"
>
}">
<template #prefix>
<img v-if="!sort" src="../thinkDynamics/images/image down.png" class="select-prefix-img" alt="" />
<img v-else src="../thinkDynamics/images/image up.png" class="select-prefix-img" alt="" />
......@@ -154,13 +144,8 @@
{{ item }}
</el-checkbox> -->
<el-checkbox class="filter-checkbox" label="全部领域"></el-checkbox>
<el-checkbox
class="filter-checkbox"
v-for="research in areaList"
:key="research.id"
v-model="selectedAreaList"
:label="research.id"
>
<el-checkbox class="filter-checkbox" v-for="research in areaList" :key="research.id"
v-model="selectedAreaList" :label="research.id">
{{ research.name }}
</el-checkbox>
</div>
......@@ -178,13 +163,8 @@
{{ item }}
</el-checkbox> -->
<el-checkbox class="filter-checkbox" label="全部领域"></el-checkbox>
<el-checkbox
class="filter-checkbox"
v-for="year in selectableYears"
:key="year"
v-model="selectedAreaList"
:label="year"
>
<el-checkbox class="filter-checkbox" v-for="year in selectableYears" :key="year"
v-model="selectedAreaList" :label="year">
{{ year }}
</el-checkbox>
</div>
......@@ -203,10 +183,7 @@
<div class="info">
{{ item.times }} · {{ item.name }}
<div class="more" @click="toDetail(item)">
<img
src="@/views/thinkTank/ThinkTankDetail/thinkDynamics/images/image open.png"
alt=""
/>
<img src="@/views/thinkTank/ThinkTankDetail/thinkDynamics/images/image open.png" alt="" />
</div>
</div>
<div class="tag-box">
......@@ -236,14 +213,8 @@
<div class="right-footer">
<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"
/>
<el-pagination :page-size="12" background layout="prev, pager, next" :total="total"
@current-change="handleCurrentChange" :current-page="currentPage" />
</div>
</div>
</div>
......@@ -262,7 +233,8 @@ import {
getThinkPolicyIndustryTotal,
getThinkPolicyIndustryChange,
getHylyList,
getThinkPolicy
getThinkPolicy,
getPolicyAdviceDeptDistribution
} from "@/api/thinkTank/overview";
import { useRouter } from "vue-router";
......@@ -311,9 +283,11 @@ const box1Data = ref([
// color: "#D6E4FF"
// }
]);
const relationBillsList = ref([{ billName: "2025《人工智能安全与评估法案》" }]);
const relationAdList = ref([{ adName: "2025《人工智能安全与评估法案》" }]);
const relationBillsList = ref([{ billName: "2025《人工智能安全与评估法案》" }])
const relationAdList = ref([{ adName: "2025《人工智能安全与评估法案》" }])
const box1SelectYear = ref("2025");
const box1YearList = ref([
{
label: "2025",
......@@ -338,23 +312,45 @@ const handleGetThinkPolicyIndustry = async () => {
const res = await getThinkPolicyIndustry(parmas);
console.log("提出建议领域分布", res);
if (res.code === 200 && res.data) {
let data = [];
res.data.map(item => {
data.push({
name: item.industry,
value: item.amount,
percent: item.percent
});
});
const list = Array.isArray(res.data) ? res.data.slice(0, 7) : [];
const data = list.map(item => ({
name: item.industry,
value: item.amount,
percent: item.percent
}));
box1Data.value = data;
const box1Chart = getPieChart(box1Data.value);
setChart(box1Chart, "box1Chart");
setChart(box1Chart, "box2Chart");
}
} catch (error) {
console.error("获取提出建议领域分布error", error);
}
};
const handleGetPolicyAdviceDeptDistribution = async () => {
try {
const parmas = {
id: router.currentRoute._value.params.id,
year: box2SelectYear.value
};
const res = await getPolicyAdviceDeptDistribution(parmas);
console.log("政策建议涉及部门分布", res);
if (res.code === 200 && res.data && Array.isArray(res.data.series)) {
// 接口新结构:data.series 为 [{ name, value, percent, extra }]
const list = res.data.series.slice(0, 7);
box2Data.value = list.map(item => ({
name: item.name,
value: item.value,
percent: item.percent
}));
const box2Chart = getPieChart(box2Data.value);
setChart(box2Chart, "box2Chart");
}
} catch (error) {
console.error("获取政策建议涉及部门分布 error", error);
}
};
// 相关政策领域分布
const box2Data = ref([]);
......@@ -651,6 +647,7 @@ onMounted(() => {
handleGetThinkPolicyIndustryChange();
handleGetHylyList();
handleGetThinkPolicy();
handleGetPolicyAdviceDeptDistribution();
});
</script>
......@@ -802,20 +799,113 @@ onMounted(() => {
}
.box-main {
height: 360px;
position: relative;
overflow: hidden;
height: 372px;
width: 520px;
box-sizing: border-box;
padding: 24px 24px 0;
#box1Chart {
height: 360px;
height: 309px;
width: 472px;
}
#box2Chart {
height: 360px;
height: 309px;
width: 472px;
}
#box3Chart {
height: 360px;
height: 309px;
width: 472px;
}
.source {
margin: 0 auto;
margin-top: 10px;
/* 上下0,左右自动居中 */
width: 370px;
height: 22px;
display: flex;
.info {
width: 16px;
height: 16px;
margin-top: 3px;
img {
width: 100%;
height: 100%;
}
}
.text {
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 14px;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
color: rgb(132, 136, 142);
margin-left: 8px;
}
}
}
.box3-main {
height: 372px;
width: 520px;
position: relative;
overflow: hidden;
box-sizing: border-box;
padding-top: 24px;
#box3Chart {
height: 300px;
width: 520px;
}
.source {
margin: 0 auto;
margin-top: 10px;
/* 上下0,左右自动居中 */
width: 370px;
height: 22px;
display: flex;
.info {
width: 16px;
height: 16px;
margin-top: 3px;
img {
width: 100%;
height: 100%;
}
}
.text {
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 14px;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
color: rgb(132, 136, 142);
margin-left: 8px;
}
}
}
}
......@@ -929,6 +1019,7 @@ onMounted(() => {
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
padding-bottom: 24px;
.select-box-science {
margin-top: 16px;
......@@ -952,12 +1043,13 @@ onMounted(() => {
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
margin-left: 24px;
.filter-checkbox {
width: 160px;
height: 24px;
margin: 0;
font-family: "Source Han Sans CN", sans-serif;
font-weight: 400;
......@@ -1043,8 +1135,8 @@ onMounted(() => {
}
.select-box-publish {
margin-top: 24px;
margin-bottom: 24px;
margin-top: 16px;
.select-box-header {
display: flex;
......@@ -1065,12 +1157,13 @@ onMounted(() => {
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
margin-left: 24px;
.filter-checkbox {
width: 160px;
height: 24px;
margin: 0;
font-family: "Source Han Sans CN", sans-serif;
font-weight: 400;
......
import * as echarts from 'echarts'
import { size, split } from 'lodash'
const getMultiLineChart = (dataX, dataY1, dataY2, dataY3) => {
return {
......@@ -19,23 +20,55 @@ const getMultiLineChart = (dataX, dataY1, dataY2, dataY3) => {
containLabel: true
},
legend: {
icon:'circle',
show: true,
top: 10,
left:'10%',
textStyle: {
fontSize: 16
}
fontSize: 16,
fontFamily: 'Source Han Sans CN',
fontWeight: 400,
lineHeight: 24,
letterSpacing: 0,
align: 'left',
color:'rgb(95, 101, 108)'
},
itemWidth:12,
itemHeight:12,
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: dataX
data: dataX,
axisLine: {
lineStyle: {
color: 'rgb(231, 243, 255)',
},
},
axisLabel: {
color: 'rgb(132, 136, 142)',
fontFamily: 'Microsoft YaHei',
fontWeight: 400,
fontSize:12,
},
}
],
yAxis: [
{
type: 'value'
type: 'value',
splitLine:{
show:true,
lineStyle:{
color:"rgb(231, 243, 255)",
type:'dashed'
}
}
}
],
series: [
......
......@@ -13,21 +13,31 @@ const getPieChart = (data) => {
},
label: {
alignTo: 'edge',
formatter: '{name|{b}} {time|{c} 条 {d}%}\n',
formatter: params => {
const name = params.name || "";
const value = params.value ?? "";
const percent = params.percent != null ? Math.round(params.percent) : 0;
return `{name|${name}}\n{time|${value}${percent}%}`;
},
minMargin: 10,
edgeDistance: 20,
lineHeight: 20,
rich: {
name: {
fontSize: 16,
color: 'rgba(59, 65, 75, 1)',
fontFamily: 'Microsoft YaHei',
fontWeight: 700
fontFamily: 'Source Han Sans CN',
fontWeight: 700,
lineHeight:24,
},
time: {
fontSize: 16,
fontSize: 14,
color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei',
fontFamily: 'Source Han Sans CN',
}
}
},
......
......@@ -18,7 +18,7 @@
</div>
</div>
<div class="header-top-right">
<button class="blue-btn">
<button class="blue-btn" @click="handleOpenThinkTankSite">
<img class="btn-img" src="./images/image1.png" alt="" />
<span class="text">{{ '查看智库官网' }}</span>
</button>
......@@ -88,6 +88,16 @@ const handleGetThinkTankSummary = async () => {
}
};
// 查看智库官网
const handleOpenThinkTankSite = () => {
const url = thinkTank.value?.url;
if (!url) {
return;
}
// 简单校验一下,防止空字符串
window.open(url, "_blank");
};
onMounted(async () => {
handleGetThinkTankSummary();
});
......
......@@ -18,7 +18,7 @@
<div class="select-research-box">
<div class="select-box-header">
<div class="icon"></div>
<div class="title">{{ "研究类型" }}</div>
<div class="title">{{ "科技领域" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
......@@ -271,16 +271,19 @@ const handleToReportDetail = item => {
};
</script>
<style lang="scss" scoped>
/* 统一智库动态国会听证会内所有 el-checkbox 文本为 16px */
:deep(.el-checkbox__label) {
font-size: 16px;
}
.main-content {
display: flex;
gap: 16px;
.left {
width: 360px;
height: 874px;
padding-bottom: 36px;
height: 100%;
padding-bottom: 24px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
......@@ -290,8 +293,8 @@ const handleToReportDetail = item => {
.select-research-box {
width: 360px;
height: 284px;
margin-top: 19px;
height: 100%;
margin-top: 16px;
.select-box-header {
display: flex;
......@@ -309,10 +312,10 @@ const handleToReportDetail = item => {
.title {
height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 26px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
......@@ -325,7 +328,7 @@ const handleToReportDetail = item => {
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
.filter-checkbox {
......@@ -343,9 +346,9 @@ const handleToReportDetail = item => {
}
.select-time-box {
margin-top: 44px;
margin-top: 16px;
width: 360px;
height: 156px;
height: 100%;
.select-box-header {
margin-bottom: 12px;
......@@ -363,10 +366,10 @@ const handleToReportDetail = item => {
.title {
height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 26px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
......@@ -379,7 +382,7 @@ const handleToReportDetail = item => {
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
.filter-checkbox {
......@@ -405,8 +408,8 @@ const handleToReportDetail = item => {
}
.select-hearing-box {
margin-top: 36px;
width: 360px;
margin-top: 16px;
width: 100%;
.select-box-header {
display: flex;
......@@ -425,9 +428,9 @@ const handleToReportDetail = item => {
height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-size: 16px;
font-weight: 700;
line-height: 26px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
......@@ -601,8 +604,4 @@ const handleToReportDetail = item => {
margin-right: 0 !important;
}
:deep(.el-checkbox__inner) {
border-radius: 4px !important;
}
</style>
\ No newline at end of file
......@@ -18,7 +18,7 @@
<div class="select-research-box">
<div class="select-box-header">
<div class="icon"></div>
<div class="title">{{ "研究类型" }}</div>
<div class="title">{{ "科技领域" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
......@@ -183,14 +183,19 @@ const handleToReportDetail = item => {
};
</script>
<style lang="scss" scoped>
/* 统一智库动态调查报告内所有 el-checkbox 文本为 16px */
:deep(.el-checkbox__label) {
font-size: 16px;
}
.main-content {
display: flex;
gap: 16px;
.left {
width: 360px;
height: 541px;
padding-bottom: 36px;
height: 100%;
padding-bottom: 24px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
......@@ -200,8 +205,8 @@ const handleToReportDetail = item => {
.select-research-box {
width: 360px;
height: 284px;
margin-top: 19px;
height: 100%;
margin-top: 16px;
.select-box-header {
display: flex;
......@@ -219,10 +224,10 @@ const handleToReportDetail = item => {
.title {
height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 26px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
......@@ -234,7 +239,7 @@ const handleToReportDetail = item => {
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
.filter-checkbox {
......@@ -260,9 +265,9 @@ const handleToReportDetail = item => {
}
.select-time-box {
margin-top: 44px;
margin-top: 16px;
width: 360px;
height: 156px;
height: 100%;
.select-box-header {
display: flex;
......@@ -280,10 +285,10 @@ const handleToReportDetail = item => {
.title {
height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 26px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
......@@ -295,7 +300,7 @@ const handleToReportDetail = item => {
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
.filter-checkbox {
......@@ -431,26 +436,4 @@ const handleToReportDetail = item => {
margin-right: 0 !important;
}
/* PolicyTracking 分页按钮样式:1px 描边 + 白底 + 6px 圆角 */
:deep(.right-footer .el-pagination.is-background .btn-prev),
:deep(.right-footer .el-pagination.is-background .btn-next),
:deep(.right-footer .el-pagination.is-background .el-pager li) {
border: 1px solid rgba(0, 0, 0, 0.15) !important;
background-color: rgba(255, 255, 255, 1) !important;
border-radius: 6px !important;
box-sizing: border-box;
}
// 选中状态的页码样式(描边+文字颜色改为指定蓝色)
:deep(.right-footer .el-pagination.is-background .el-pager li.is-active) {
border-color: rgba(22, 119, 255, 1) !important; // 选中后描边颜色
color: rgba(22, 119, 255, 1) !important; // 选中后页码文字颜色
background-color: rgba(255, 255, 255, 1) !important; // 保持白色背景
font-weight: 400;
}
:deep(.el-checkbox__inner) {
border-radius: 4px !important;
}
</style>
\ No newline at end of file
......@@ -18,7 +18,7 @@
<div class="select-research-box">
<div class="select-box-header">
<div class="icon"></div>
<div class="title">{{ "研究类型" }}</div>
<div class="title">{{ "科技领域" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
......@@ -183,14 +183,19 @@ const handleToReportDetail = item => {
};
</script>
<style lang="scss" scoped>
/* 统一智库动态智库报告内所有 el-checkbox 文本为 16px */
:deep(.el-checkbox__label) {
font-size: 16px;
}
.main-content {
display: flex;
gap: 16px;
.left {
width: 360px;
height: 541px;
padding-bottom: 36px;
height: 100%;
padding-bottom: 24px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
......@@ -200,8 +205,8 @@ const handleToReportDetail = item => {
.select-research-box {
width: 360px;
height: 284px;
margin-top: 19px;
height: 100%;
margin-top: 16px;
.select-box-header {
display: flex;
......@@ -219,10 +224,10 @@ const handleToReportDetail = item => {
.title {
height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 26px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
......@@ -234,7 +239,7 @@ const handleToReportDetail = item => {
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
.filter-checkbox {
......@@ -260,9 +265,9 @@ const handleToReportDetail = item => {
}
.select-time-box {
margin-top: 44px;
margin-top: 16px;
width: 360px;
height: 156px;
height: 100%;
.select-box-header {
display: flex;
......@@ -280,10 +285,10 @@ const handleToReportDetail = item => {
.title {
height: 26px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 26px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
......@@ -295,7 +300,7 @@ const handleToReportDetail = item => {
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
.filter-checkbox {
......@@ -431,26 +436,4 @@ const handleToReportDetail = item => {
margin-right: 0 !important;
}
/* PolicyTracking 分页按钮样式:1px 描边 + 白底 + 6px 圆角 */
:deep(.right-footer .el-pagination.is-background .btn-prev),
:deep(.right-footer .el-pagination.is-background .btn-next),
:deep(.right-footer .el-pagination.is-background .el-pager li) {
border: 1px solid rgba(0, 0, 0, 0.15) !important;
background-color: rgba(255, 255, 255, 1) !important;
border-radius: 6px !important;
box-sizing: border-box;
}
// 选中状态的页码样式(描边+文字颜色改为指定蓝色)
:deep(.right-footer .el-pagination.is-background .el-pager li.is-active) {
border-color: rgba(22, 119, 255, 1) !important; // 选中后描边颜色
color: rgba(22, 119, 255, 1) !important; // 选中后页码文字颜色
background-color: rgba(255, 255, 255, 1) !important; // 保持白色背景
font-weight: 400;
}
:deep(.el-checkbox__inner) {
border-radius: 4px !important;
}
</style>
\ No newline at end of file
......@@ -72,25 +72,22 @@
<div v-if="isThinkTankReport">
<ThinkTankReport :research-type-list="researchTypeList" :research-time-list="researchTimeList"
:key="`智库报告-${tabResetKey}`" :selected-filters="selectedFilters" :cur-footer-list="curFooterList" :total="total"
:current-page="currentPage"
@update:selected-filters="handleSelectedFiltersUpdate"
:current-page="currentPage" @update:selected-filters="handleSelectedFiltersUpdate"
@filter-change="(payload) => handleGetThinkDynamicsReport(payload)" @page-change="handleCurrentChange"
@report-click="handleToReportDetail" />
</div>
<div v-if="isCongressHearing">
<CongressHearing :research-type-list="researchTypeList" :research-time-list="researchTimeList"
:key="`国会听证会-${tabResetKey}`" :research-hearing-list="researchHearingList"
:selected-filters="selectedFilters" :selected-year="selectedYear" :cur-footer-list="curFooterList" :total="total"
:current-page="currentPage" :hearing-data="hearingData"
@update:selected-filters="handleSelectedFiltersUpdate"
:key="`国会听证会-${tabResetKey}`" :research-hearing-list="researchHearingList" :selected-filters="selectedFilters"
:selected-year="selectedYear" :cur-footer-list="curFooterList" :total="total" :current-page="currentPage"
:hearing-data="hearingData" @update:selected-filters="handleSelectedFiltersUpdate"
@filter-change="(payload) => handleGetThinkDynamicsReport(payload)" @page-change="handleCurrentChange"
@report-click="handleToReportDetail" />
</div>
<div>
<SurveyForm v-if="isSurveyForm" :research-type-list="researchTypeList" :research-time-list="researchTimeList"
:key="`调查项目-${tabResetKey}`" :selected-filters="selectedFilters" :cur-footer-list="curFooterList" :total="total"
:current-page="currentPage"
@update:selected-filters="handleSelectedFiltersUpdate"
:current-page="currentPage" @update:selected-filters="handleSelectedFiltersUpdate"
@filter-change="(payload) => handleGetThinkDynamicsReport(payload)" @page-change="handleCurrentChange"
@report-click="handleToReportDetail" />
</div>
......@@ -633,8 +630,9 @@ onMounted(async () => {
<style lang="scss" scoped>
.main-header {
height: 64px;
width: 1600px;
margin-bottom: 16px;
display: flex;
align-items: center;
background: rgb(255, 255, 255);
......@@ -889,62 +887,4 @@ onMounted(async () => {
}
}
:deep(.el-pagination) {
display: flex;
align-items: center;
}
:deep(.el-pagination.is-background .el-pager li) {
min-width: 32px;
height: 32px;
line-height: 32px;
border-radius: 6px;
margin: 0 6px;
border: 1px solid rgba(0, 0, 0, 0.15);
background-color: #fff;
color: rgb(95, 101, 108);
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
}
:deep(.el-pagination.is-background .el-pager li.is-active) {
background-color: #fff;
color: rgba(22, 119, 255, 1);
border-color: rgba(22, 119, 255, 1);
}
:deep(.el-pagination.is-background .el-pager li.is-ellipsis) {
border: none;
background-color: transparent;
color: rgb(95, 101, 108);
min-width: 16px;
margin: 0 6px;
}
:deep(.el-pagination.is-background .btn-prev),
:deep(.el-pagination.is-background .btn-next) {
min-width: 32px;
height: 32px;
border-radius: 6px;
border: 1px solid rgba(0, 0, 0, 0.15);
background-color: #fff;
color: rgb(95, 101, 108);
font-size: 16px;
font-family: "Microsoft YaHei";
margin: 0 6px;
}
:deep(.el-pagination.is-background .btn-prev.is-disabled),
:deep(.el-pagination.is-background .btn-next.is-disabled) {
color: rgba(95, 101, 108, 0.45);
border-color: rgb(235, 238, 242);
background-color: #fff;
}
</style>
\ No newline at end of file
......@@ -113,6 +113,10 @@
</div>
<div class="box1-main-right" id="box1Chart"></div>
</div>
<div class="source">
<div class="info"><img src="./images/image-exclamation.png"></div>
<div class="text"> 数据来源:美国国会官网,数据时间:2015.1至2025.12</div>
</div>
</AnalysisBox>
</div>
<div class="box">
......@@ -211,7 +215,13 @@
</div> -->
<AnalysisBox title="核心研究人员">
<div class="box3-main">
<div class="box3-main-left" id="box3Chart"></div>
<div class="box3-main-left">
<div id="box3Chart"></div>
<div class="source">
<div class="info"><img src="./images/image-exclamation.png"></div>
<div class="text"> 数据来源:美国国会官网,数据时间:2015.1至2025.12</div>
</div>
</div>
<div class="box3-main-right">
<div class="box3-right-item" v-for="(item, index) in box3RightData" :key="index">
<div class="icon" @click="handleClickPerson(item)">
......@@ -250,6 +260,7 @@ import {
import { useRouter } from "vue-router";
import DefaultIcon1 from '@/assets/icons/default-icon1.png'
import { getPersonSummaryInfo } from "@/api/common/index";
const router = useRouter();
import InfoImg from "./images/img.png";
......@@ -392,13 +403,11 @@ const handleGetThinkTankFundsSource = async () => {
console.log("获取经费来源", res);
if (res.code === 200 && res.data) {
let data = []
res.data.map(item => {
data.push({
name: item.institution,
value: item.amount,
})
})
const topList = Array.isArray(res.data) ? res.data.slice(0, 7) : []
const data = topList.map(item => ({
name: item.institution,
value: item.amount,
}))
box1ChartData.value = data
const box1Chart = getPieChart(box1ChartData.value);
......@@ -664,18 +673,64 @@ const handleGetThinkPerson = async () => {
};
// 点击人物头像,跳转到人物主页
const handleClickPerson = (item) => {
console.log('item', item);
window.sessionStorage.setItem("curTabName", item.name)
const route = router.resolve({
path: "/characterPage",
query: {
type: 3 // 1 2 3
const handleClickPerson = async item => {
console.log("person", item);
const personTypeList = JSON.parse(window.sessionStorage.getItem("personTypeList"));
console.log("personTypeList", personTypeList);
let type = 0;
let personTypeName = "";
const params = {
personId: item.personId
};
try {
const res = await getPersonSummaryInfo(params);
console.log("人物全局信息", res);
if (res.code === 200 && res.data) {
const arr = personTypeList.filter(t => {
const typeIdNum = Number(t.typeId);
const personTypeNum = Number(res.data.personType);
return !Number.isNaN(typeIdNum) && !Number.isNaN(personTypeNum) && typeIdNum === personTypeNum;
});
console.log("arr", arr);
if (arr && arr.length > 0) {
personTypeName = arr[0].typeName;
console.log("personTypeName", personTypeName);
if (personTypeName === "科技企业领袖") {
type = 1;
} else if (personTypeName === "国会议员") {
type = 2;
} else if (personTypeName === "智库研究人员") {
type = 3;
} else {
personTypeName = "";
ElMessage.warning("找不到当前人员的类型值!");
return;
}
window.sessionStorage.setItem("curTabName", item.name);
const route = router.resolve({
path: "/characterPage",
query: {
type: type, // type=1为科技企业领袖,2为国会议员,3为智库研究人员
personId: item.personId
}
});
window.open(route.href, "_blank");
} else {
personTypeName = "";
ElMessage.warning("找不到当前人员的类型值!");
return;
}
} else {
ElMessage.warning("找不到当前人员的类型值!");
return;
}
});
window.open(route.href, "_blank");
} catch (error) { }
};
onMounted(() => {
handleGetThinkTankInfoBasic()
handleGetThinkTankInfoBranch()
......@@ -1005,6 +1060,42 @@ onMounted(() => {
}
}
.source {
margin: 0 auto;
margin-top: 10px;
/* 上下0,左右自动居中 */
width: 370px;
height: 22px;
display: flex;
.info {
width: 16px;
height: 16px;
margin-top: 3px;
img {
width: 100%;
height: 100%;
}
}
.text {
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 14px;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
color: rgb(132, 136, 142);
margin-left: 8px;
}
}
.box2-main {
height: 320px;
display: flex;
......@@ -1144,6 +1235,48 @@ onMounted(() => {
width: 536px;
height: 326px;
margin-left: 9px;
box-sizing: border-box;
#box3Chart {
width: 536px;
height: 290px;
}
.source {
margin: 0 auto;
margin-top: 10px;
/* 上下0,左右自动居中 */
width: 370px;
height: 22px;
display: flex;
.info {
width: 16px;
height: 16px;
margin-top: 3px;
img {
width: 100%;
height: 100%;
}
}
.text {
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 14px;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
color: rgb(132, 136, 142);
margin-left: 8px;
}
}
}
......@@ -1222,6 +1355,8 @@ onMounted(() => {
}
}
}
}
}
}
......
<template>
<div class="home-main-footer-main">
<div class="left">
<div class="select-box">
<div class="header">
<div class="icon"></div>
<div class="title">{{ "科技领域" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox v-model="checkAllModel" class="all-checkbox" @change="emit('check-all-change', $event)">
全部领域
</el-checkbox>
<el-checkbox v-for="research in areaList" :key="research.id" v-model="selectedAreaListModel"
:label="research.id" @change="emit('checked-area-change')" class="filter-checkbox">
{{ research.name }}
</el-checkbox>
</div>
</div>
</div>
<div class="select-box">
<div class="header">
<div class="icon"></div>
<div class="title">{{ "发布时间" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox v-model="checkAllTimeModel" class="all-checkbox"
@change="emit('check-all-time-change', $event)">
全部时间
</el-checkbox>
<el-checkbox v-for="time in pubTimeList" :key="time.id" v-model="selectedPubTimeListModel" :label="time.id"
class="filter-checkbox" @change="emit('checked-area-time-change')">
{{ time.name }}
</el-checkbox>
</div>
</div>
</div>
</div>
<div class="right">
<div class="card-box">
<div class="footer-card" v-for="(item, index) in curFooterList" :key="index"
@click="emit('report-click', item)">
<div class="footer-card-top">
<img :src="item.imageUrl" alt="" />
</div>
<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>
</div>
</div>
</div>
<div class="right-footer">
<div class="info">{{ total }} 篇政府报告</div>
<div class="page-box">
<el-pagination :page-size="12" background layout="prev, pager, next" :total="total"
@current-change="emit('page-change', $event)" :current-page="currentPage" />
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from "vue";
const props = defineProps({
checkAll: { type: Boolean, default: false },
isIndeterminate: { type: Boolean, default: false },
areaList: { type: Array, default: () => [] },
selectedAreaList: { type: Array, default: () => [] },
checkAllTime: { type: Boolean, default: false },
isIndeterminateTime: { type: Boolean, default: false },
pubTimeList: { type: Array, default: () => [] },
selectedPubTimeList: { type: Array, default: () => [] },
curFooterList: { type: Array, default: () => [] },
total: { type: Number, default: 0 },
currentPage: { type: Number, default: 1 }
});
const emit = defineEmits([
"update:checkAll",
"update:selectedAreaList",
"check-all-change",
"checked-area-change",
"update:checkAllTime",
"update:selectedPubTimeList",
"check-all-time-change",
"checked-area-time-change",
"report-click",
"page-change"
]);
const checkAllModel = computed({
get: () => props.checkAll,
set: val => emit("update:checkAll", val)
});
const selectedAreaListModel = computed({
get: () => props.selectedAreaList,
set: val => emit("update:selectedAreaList", val)
});
const checkAllTimeModel = computed({
get: () => props.checkAllTime,
set: val => emit("update:checkAllTime", val)
});
const selectedPubTimeListModel = computed({
get: () => props.selectedPubTimeList,
set: val => emit("update:selectedPubTimeList", val)
});
</script>
<style lang="scss" scoped>
.home-main-footer-main {
margin: 0 auto;
margin-top: 36px;
width: 1600px;
display: flex;
gap: 16px;
.left {
width: 360px;
height: 100%;
padding-bottom: 24px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1);
background: rgba(255, 255, 255, 1);
position: relative;
.select-box {
margin-top: 16px;
.header {
display: flex;
gap: 17px;
.icon {
margin-top: 4px;
width: 8px;
height: 16px;
background: var(--color-main-active);
border-radius: 0 4px 4px 0;
}
.title {
height: 24px;
color: var(--color-main-active);
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
}
.select-main {
margin-left: 24px;
margin-top: 12px;
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
.all-checkbox {
width: 160px;
height: 24px;
margin: 0;
}
.filter-checkbox {
width: 160px;
height: 24px;
margin-right: 0 !important;
}
}
}
.select-main1 {
width: 100px;
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
.filter-checkbox {
width: 160px;
height: 24px;
margin-right: 0 !important;
}
}
}
}
}
.right {
width: 1284px;
max-height: 1377px;
.card-box {
width: 1226px;
max-height: 1248px;
min-height: 616px;
display: flex;
flex-wrap: wrap;
gap: 16px 16px;
.footer-card {
width: 398px;
height: 300px;
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.footer-card-top {
width: 364px;
height: 180px;
margin: 0 auto;
margin-top: 15px;
img {
width: 100%;
height: 100%;
}
}
.footer-card-title {
margin: 0 auto;
margin-top: 13px;
width: 376px;
height: 48px;
/* 修改高度为两行的高度 */
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
line-height: 24px;
overflow: hidden;
/* 隐藏超出部分 */
text-overflow: ellipsis;
/* 显示省略号 */
display: -webkit-box;
/* 使用弹性盒模型 */
-webkit-line-clamp: 2;
/* 限制显示两行 */
-webkit-box-orient: vertical;
/* 设置盒模型方向为垂直 */
}
.footer-card-footer {
margin: 0 auto;
margin-top: 5px;
width: 376px;
height: 22px;
display: flex;
justify-content: space-between;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
}
.right-footer {
height: 50px;
margin-top: 43px;
display: flex;
justify-content: space-between;
.info {
height: 19px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
}
}
}
}
.filter-checkbox {
width: 160px;
height: 24px;
margin: 0;
}
</style>
<template>
<!-- 调查项目:结构/样式与智库报告一致,但组件独立,避免互相影响 -->
<div class="home-main-footer-main">
<div class="left">
<div class="select-box">
<div class="header">
<div class="icon"></div>
<div class="title">{{ "科技领域" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox v-model="checkAllModel" class="all-checkbox" @change="emit('check-all-change', $event)">
全部领域
</el-checkbox>
<el-checkbox v-for="research in areaList" :key="research.id" v-model="selectedAreaListModel"
:label="research.id" @change="emit('checked-area-change')" class="filter-checkbox">
{{ research.name }}
</el-checkbox>
</div>
</div>
</div>
<div class="select-box">
<div class="header">
<div class="icon"></div>
<div class="title">{{ "发布时间" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox v-model="checkAllTimeModel" class="all-checkbox"
@change="emit('check-all-time-change', $event)">
全部时间
</el-checkbox>
<el-checkbox v-model="selectedPubTimeListModel" v-for="time in pubTimeList" :key="time.id" :label="time.id"
class="filter-checkbox" @change="emit('checked-area-time-change')">
{{ time.name }}
</el-checkbox>
</div>
</div>
</div>
</div>
<div class="right">
<div class="card-box">
<div class="footer-card" v-for="(item, index) in curFooterList" :key="index"
@click="emit('report-click', item)">
<div class="footer-card-top">
<img :src="item.imageUrl" alt="" />
</div>
<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>
</div>
</div>
</div>
<div class="right-footer">
<div class="info">{{ total }} 篇智库报告</div>
<div class="page-box">
<el-pagination :page-size="12" background layout="prev, pager, next" :total="total"
@current-change="emit('page-change', $event)" :current-page="currentPage" />
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from "vue";
const props = defineProps({
checkAll: { type: Boolean, default: false },
isIndeterminate: { type: Boolean, default: false },
areaList: { type: Array, default: () => [] },
selectedAreaList: { type: Array, default: () => [] },
checkAllTime: { type: Boolean, default: false },
isIndeterminateTime: { type: Boolean, default: false },
pubTimeList: { type: Array, default: () => [] },
selectedPubTimeList: { type: Array, default: () => [] },
curFooterList: { type: Array, default: () => [] },
total: { type: Number, default: 0 },
currentPage: { type: Number, default: 1 }
});
const emit = defineEmits([
"update:checkAll",
"update:selectedAreaList",
"check-all-change",
"checked-area-change",
"update:checkAllTime",
"update:selectedPubTimeList",
"check-all-time-change",
"checked-area-time-change",
"report-click",
"page-change"
]);
const checkAllModel = computed({
get: () => props.checkAll,
set: val => emit("update:checkAll", val)
});
const selectedAreaListModel = computed({
get: () => props.selectedAreaList,
set: val => emit("update:selectedAreaList", val)
});
const checkAllTimeModel = computed({
get: () => props.checkAllTime,
set: val => emit("update:checkAllTime", val)
});
const selectedPubTimeListModel = computed({
get: () => props.selectedPubTimeList,
set: val => emit("update:selectedPubTimeList", val)
});
</script>
<style lang="scss" scoped>
/* 复制 HomeMainFooterMain 的样式,保证完全不影响外观 */
.home-main-footer-main {
margin: 0 auto;
margin-top: 36px;
width: 1600px;
display: flex;
gap: 16px;
.left {
width: 360px;
height: 100%;
padding-bottom: 24px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1);
background: rgba(255, 255, 255, 1);
position: relative;
.select-box {
margin-top: 16px;
.header {
display: flex;
gap: 17px;
.icon {
margin-top: 4px;
width: 8px;
height: 16px;
background: var(--color-main-active);
border-radius: 0 4px 4px 0;
}
.title {
height: 24px;
color: var(--color-main-active);
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
}
.select-main {
margin-left: 24px;
margin-top: 12px;
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
}
}
.select-main1 {
width: 100px;
}
}
}
.right {
width: 1284px;
max-height: 1377px;
.card-box {
width: 1226px;
max-height: 1248px;
min-height: 616px;
display: flex;
flex-wrap: wrap;
gap: 16px 16px;
.footer-card {
width: 398px;
height: 300px;
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.footer-card-top {
width: 364px;
height: 180px;
margin: 0 auto;
margin-top: 15px;
img {
width: 100%;
height: 100%;
}
}
.footer-card-title {
margin: 0 auto;
margin-top: 13px;
width: 376px;
height: 48px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 18px;
font-weight: 700;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.footer-card-footer {
margin: 0 auto;
margin-top: 5px;
width: 376px;
height: 22px;
display: flex;
justify-content: space-between;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
}
}
.right-footer {
height: 50px;
margin-top: 43px;
display: flex;
justify-content: space-between;
.info {
height: 19px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
}
}
}
}
.all-checkbox {
width: 160px;
height: 24px;
margin: 0;
}
.filter-checkbox {
width: 160px;
height: 24px;
margin: 0;
}
</style>
<template>
<div class="home-main-footer-main">
<div class="left">
<div class="select-research-box">
<div class="select-box-header">
<div class="icon"></div>
<div class="title">{{ "科技领域" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox class="filter-checkbox" :model-value="isGroupAllSelected(researchTypeIds)"
@change="val => handleToggleAll(val, researchTypeIds)">
全部领域
</el-checkbox>
<el-checkbox v-for="type in researchTypeList" :key="type.id" v-model="selectedResearchIds" :label="type.id"
class="filter-checkbox" @change="handleFilterChange">
{{ type.name }}
</el-checkbox>
</div>
</div>
</div>
<div class="select-time-box">
<div class="select-box-header">
<div class="icon"></div>
<div class="title">{{ "发布时间" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox class="filter-checkbox" :model-value="isGroupAllSelected(researchTimeIds)"
@change="val => handleToggleAll(val, researchTimeIds)">
全部时间
</el-checkbox>
<el-checkbox v-for="type in researchTimeList" :key="type.id" v-model="selectedResearchTimeIds"
:label="type.id" class="filter-checkbox" @change="handleFilterChange">
{{ type.name }}
</el-checkbox>
</div>
</div>
</div>
<div class="select-hearing-box">
<div class="select-box-header">
<div class="icon"></div>
<div class="title">{{ "听证会部门" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group hearing-grid">
<el-checkbox class="filter-checkbox" :model-value="isGroupAllSelected(researchHearingIds)"
@change="val => handleToggleAll(val, researchHearingIds)">
全部部门
</el-checkbox>
<el-checkbox v-for="type in researchHearingList" :key="type.id" v-model="selectedResearchHearingIds"
:label="type.id" class="filter-checkbox" @change="handleFilterChange">
{{ type.name }}
</el-checkbox>
</div>
</div>
</div>
</div>
<div class="right">
<div class="card-box">
<div class="card-content">
<div v-for="(item, index) in displayList" :key="item.id ?? index">
<div class="card-item" @click="emit('report-click', item)">
<img class="card-item-img" src="../ThinkTankDetail/thinkDynamics/images/img congress.png"
alt="report image" />
<div class="card-item-text">
<div class="card-item-title">
{{ item.title }}
</div>
<div class="card-item-time">
{{ item.time + ' · ' + item.content }}
<img src="../ThinkTankDetail/thinkDynamics/images/image open.png" alt="open icon"
class="card-open-image" />
</div>
<div class="card-item-category">
<AreaTag :key="index" :tagName="item.category">
</AreaTag>
</div>
</div>
</div>
<div class="divider" v-if="index !== displayList.length - 1"></div>
</div>
</div>
</div>
<div class="right-footer">
<div class="info">
{{ filteredHearingData.length }} 篇智库报告
</div>
<div class="page-box">
<el-pagination :page-size="pageSize" background layout="prev, pager, next" :total="filteredHearingData.length"
@current-change="handlePageChange" :current-page="currentPage" />
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed, ref } from "vue";
const props = defineProps({
researchTypeList: { type: Array, default: () => [] },
researchTimeList: { type: Array, default: () => [] },
});
const emit = defineEmits(["report-click"]);
const pageSize = 10;
const currentPage = ref(1);
const selectedResearchIds = ref([]);
const selectedResearchTimeIds = ref([]);
const selectedResearchHearingIds = ref([]);
// 概览页暂无独立接口时,先使用一份静态数据(结构与智库动态保持一致)
const hearingData = ref([
{ id: 1, title: "美国国会听证会:人工智能与国家安全", content: "美中经济与安全审查委员会", category: "人工智能", time: "2025年7月8日" },
{ id: 2, title: "美国国会听证会:先进制造供应链韧性", content: "国会-行政部门中国委员会", category: "先进制造", time: "2025年6月15日" },
{ id: 3, title: "美国国会听证会:半导体出口管制与产业政策", content: "美国商务部", category: "半导体", time: "2025年5月22日" },
{ id: 4, title: "美国国会听证会:人工智能与国家安全", content: "美中经济与安全审查委员会", category: "人工智能", time: "2025年7月8日" },
{ id: 5, title: "美国国会听证会:先进制造供应链韧性", content: "国会-行政部门中国委员会", category: "先进制造", time: "2025年6月15日" },
{ id: 6, title: "美国国会听证会:半导体出口管制与产业政策", content: "美国商务部", category: "半导体", time: "2025年5月22日" },
{ id: 7, title: "美国国会听证会:人工智能与国家安全", content: "美中经济与安全审查委员会", category: "人工智能", time: "2025年7月8日" },
{ id: 8, title: "美国国会听证会:先进制造供应链韧性", content: "国会-行政部门中国委员会", category: "先进制造", time: "2025年6月15日" },
{ id: 9, title: "美国国会听证会:半导体出口管制与产业政策", content: "美国商务部", category: "半导体", time: "2025年5月22日" },
{ id: 10, title: "美国国会听证会:人工智能与国家安全", content: "美中经济与安全审查委员会", category: "人工智能", time: "2025年7月8日" },
{ id: 11, title: "美国国会听证会:先进制造供应链韧性", content: "国会-行政部门中国委员会", category: "先进制造", time: "2025年6月15日" },
{ id: 12, title: "美国国会听证会:半导体出口管制与产业政策", content: "美国商务部", category: "半导体", time: "2025年5月22日" },
]);
const researchHearingList = ref([
{ id: "美中经济与安全审查委员会", name: "美中经济与安全审查委员会" },
{ id: "国会-行政部门中国委员会", name: "国会-行政部门中国委员会" },
{ id: "美国商务部", name: "美国商务部" },
]);
const researchTypeIds = computed(() => (props.researchTypeList || []).map(item => item.id));
const researchTimeIds = computed(() => (props.researchTimeList || []).map(item => item.id));
const researchHearingIds = computed(() => (researchHearingList.value || []).map(item => item.id));
const getTargetSelection = ids => {
if (ids === researchTypeIds.value) return selectedResearchIds;
if (ids === researchTimeIds.value) return selectedResearchTimeIds;
return selectedResearchHearingIds;
};
const isGroupAllSelected = ids =>
ids.length > 0 && ids.every(id => getTargetSelection(ids).value.includes(id));
const handleToggleAll = (checked, ids) => {
if (!ids.length) return;
const targetSelection = getTargetSelection(ids);
const nextSelected = new Set(targetSelection.value);
if (checked) {
ids.forEach(id => nextSelected.add(id));
} else {
ids.forEach(id => nextSelected.delete(id));
}
targetSelection.value = [...nextSelected];
handleFilterChange();
};
const filteredHearingData = computed(() => {
return (hearingData.value || []).filter(item => {
const matchYear =
selectedResearchTimeIds.value.length === 0 ||
selectedResearchTimeIds.value.some(year => String(item.time || "").startsWith(year));
const matchDepartment =
selectedResearchHearingIds.value.length === 0 ||
selectedResearchHearingIds.value.some(department =>
String(item.content || "").includes(department) || String(item.title || "").includes(department)
);
const matchType =
selectedResearchIds.value.length === 0 ||
selectedResearchIds.value.some(typeId =>
String(item.category || "").includes(typeId) || String(item.title || "").includes(typeId)
);
return matchYear && matchDepartment && matchType;
});
});
const displayList = computed(() => {
const list = filteredHearingData.value || [];
const start = (currentPage.value - 1) * pageSize;
return list.slice(start, start + pageSize);
});
const handleFilterChange = () => {
currentPage.value = 1;
};
const handlePageChange = page => {
currentPage.value = page;
};
</script>
<style lang="scss" scoped>
/* 统一资源库国会听证会内所有 el-checkbox 文本为 16px */
:deep(.el-checkbox__label) {
font-size: 16px;
}
/* 外层对齐智库报告资源库布局 */
.home-main-footer-main {
margin: 0 auto;
margin-top: 36px;
width: 1600px;
display: flex;
gap: 16px;
}
.left {
width: 360px;
height: 100%;
padding-bottom: 24px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1);
background: rgba(255, 255, 255, 1);
position: relative;
}
.select-box-header {
display: flex;
gap: 17px;
.icon {
margin-top: 4px;
width: 8px;
height: 16px;
background: var(--color-main-active);
border-radius: 0 4px 4px 0;
}
.title {
height: 24px;
color: var(--color-main-active);
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
}
}
.select-research-box {
width: 360px;
height: 284px;
margin-top: 16px;
}
.select-time-box {
margin-top: 16px;
width: 360px;
}
.select-hearing-box {
margin-top: 16px;
width: 360px;
}
.select-main {
margin-left: 24px;
margin-top: 12px;
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
.filter-checkbox {
width: 160px;
height: 24px;
margin-right: 0 !important;
}
}
.hearing-grid {
grid-template-columns: 160px;
width: 259px;
gap: 4px;
}
}
.right {
width: 1224px;
height: 1377px;
.card-box {
width: 100%;
height: 1134px;
display: flex;
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1);
padding-right: 36px;
.card-content {
width: 1211px;
height: 1067px;
margin-top: 33px;
margin-left: 37px;
}
}
.right-footer {
margin-top: 43px;
display: flex;
justify-content: space-between;
.info {
height: 19px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
}
}
}
.card-item {
width: 100%;
height: 77px;
display: flex;
align-items: center;
.card-item-img {
width: 56px;
height: 77px;
margin-right: 22px;
flex-shrink: 0;
}
.card-item-text {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
.card-item-title {
color: rgb(59, 65, 75);
font-family: "Source Han Sans CN";
font-size: 18px;
font-weight: 700;
line-height: 22px;
margin-bottom: 2px;
display: inline-flex;
}
.card-item-time {
color: rgb(95, 101, 108);
font-family: "Source Han Sans CN";
font-size: 14px;
font-weight: 400;
line-height: 22px;
margin-bottom: 7px;
text-align: left;
display: inline-flex;
.card-open-image {
width: 16px;
height: 16px;
margin-left: 9px;
margin-top: 3px;
}
}
.card-item-category {
gap: 8px;
height: 24px;
display: flex;
}
}
}
.divider {
height: 1px;
background: rgb(234, 236, 238);
margin: 16px 0;
}
</style>
<template>
<div class="home-main-footer-main">
<div class="left">
<div class="select-box-science">
<div class="select-box-header">
<div class="icon"></div>
<div class="title">{{ "科技领域" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox class="filter-checkbox" :model-value="isAllSelected(typeIds)"
@change="val => toggleAll(val, typeIds)">
全部领域
</el-checkbox>
<el-checkbox class="filter-checkbox" v-for="t in (researchTypeList || [])" :key="t.id"
v-model="selectedTypeIds" :label="t.id" @change="emitChange">
{{ t.name }}
</el-checkbox>
</div>
</div>
</div>
<div class="select-box-publish">
<div class="select-box-header">
<div class="icon"></div>
<div class="title">{{ "发布时间" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox class="filter-checkbox" :model-value="isAllSelected(yearIds)"
@change="val => toggleAll(val, yearIds)">
全部时间
</el-checkbox>
<el-checkbox class="filter-checkbox" v-for="y in (researchTimeList || [])" :key="y.id"
v-model="selectedYearIds" :label="y.id" @change="emitChange">
{{ y.name }}
</el-checkbox>
</div>
</div>
</div>
</div>
<div class="right">
<div class="card-box">
<div class="card-content">
<div v-for="(item, index) in list" :key="item.id ?? index">
<div class="card-item" @click="emit('item-click', item)">
<div class="card-item-img">
<img :src="item.imageUrl" alt="" />
</div>
<div class="card-item-text">
<div class="card-item-title">{{ item.name }}</div>
<div class="card-item-time">
<span class="info-text">{{ item.times }} · {{ item.thinkTankName }} · {{ item.reportName }}</span>
<div class="card-open-image">
<img src="@/views/thinkTank/ThinkTankDetail/thinkDynamics/images/image open.png" alt="" />
</div>
</div>
<div class="card-item-category" v-if="item.tagList && item.tagList.length">
<AreaTag v-for="d in item.tagList" :key="d" :tagName="d" />
</div>
<div class="file-box">
<div class="file">
<div class="type">法案</div>
<div class="title">{{ item.billInfoList[0].name }}</div>
<div class="more">
<img src="../assets/images/image-right.png" alt="" />
</div>
</div>
<div class="file">
<div class="type">政令</div>
<div class="title">{{ item.billInfoList[0].name }}</div>
<div class="more">
<img src="../assets/images/image-right.png" alt="" />
</div>
</div>
</div>
</div>
</div>
<div class="divider" v-if="index !== list.length - 1"></div>
</div>
</div>
</div>
<div class="right-footer">
<div class="info">{{ total }}篇智库报告</div>
<div class="page-box">
<el-pagination :page-size="pageSize" background layout="prev, pager, next" :total="total"
@current-change="p => emit('page-change', p)" :current-page="currentPage" />
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed, ref } from "vue";
import AreaTag from "@/components/base/AreaTag/index.vue";
const props = defineProps({
researchTypeList: { type: Array, default: () => [] },
researchTimeList: { type: Array, default: () => [] },
list: { type: Array, default: () => [] },
total: { type: Number, default: 0 },
currentPage: { type: Number, default: 1 },
pageSize: { type: Number, default: 7 },
});
const emit = defineEmits(["filter-change", "page-change", "item-click"]);
const selectedTypeIds = ref([]);
const selectedYearIds = ref([]);
const typeIds = computed(() => (props.researchTypeList || []).map(i => i.id));
const yearIds = computed(() => (props.researchTimeList || []).map(i => i.id));
const isAllSelected = ids => ids.length > 0 && ids.every(id => {
const target = ids === typeIds.value ? selectedTypeIds.value : selectedYearIds.value
return target.includes(id)
});
const toggleAll = (checked, ids) => {
const target = ids === typeIds.value ? selectedTypeIds : selectedYearIds
target.value = checked ? [...ids] : []
emitChange()
}
const emitChange = () => {
emit("filter-change", {
researchTypeIds: [...selectedTypeIds.value],
researchTimeIds: [...selectedYearIds.value],
})
}
</script>
<style lang="scss" scoped>
/* 最外层对齐智库报告资源库布局 */
.home-main-footer-main {
margin: 0 auto;
margin-top: 36px;
width: 1600px;
display: flex;
gap: 16px;
.left {
width: 360px;
height: 100%;
padding-bottom: 24px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
.select-box-science {
margin-top: 16px;
.select-box-header {
display: flex;
.icon {
margin-top: 4px;
width: 8px;
height: 16px;
background: var(--color-main-active);
border-radius: 0 4px 4px 0;
}
.title {
margin-left: 17px;
font-family: "Source Han Sans CN";
font-weight: 700;
font-size: 16px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
color: rgba(5, 95, 194, 1);
}
}
.select-main {
margin-top: 12px;
}
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
margin-left: 24px;
.filter-checkbox {
width: 160px;
margin: 0;
height: 24px;
font-family: "Source Han Sans CN", sans-serif;
font-weight: 400;
font-size: 16px;
line-height: 24px;
letter-spacing: 0px;
text-align: justify;
}
}
}
.select-box-publish {
margin-top: 16px;
.select-box-header {
display: flex;
.icon {
margin-top: 4px;
width: 8px;
height: 16px;
background: var(--color-main-active);
border-radius: 0 4px 4px 0;
}
.title {
margin-left: 17px;
font-family: "Source Han Sans CN";
font-weight: 700;
font-size: 16px;
line-height: 24px;
letter-spacing: 1px;
text-align: left;
color: rgba(5, 95, 194, 1);
}
}
.select-main {
margin-top: 12px;
}
.checkbox-group {
display: grid;
grid-template-columns: repeat(2, 160px);
gap: 8px 4px;
margin-left: 24px;
.filter-checkbox {
width: 160px;
margin: 0;
height: 24px;
font-family: "Source Han Sans CN", sans-serif;
font-weight: 400;
font-size: 16px;
line-height: 24px;
letter-spacing: 0px;
text-align: justify;
}
}
}
}
.right {
width: 1224px;
height: 1377px;
.card-box {
width: 100%;
height: 1134px;
display: flex;
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1);
padding-right: 36px;
.card-content {
width: 1211px;
height: 1067px;
margin-top: 33px;
margin-left: 37px;
}
}
.card-item {
width: 100%;
height: 100%;
display: flex;
.card-item-img {
width: 56px;
height: 77px;
margin-right: 22px;
flex-shrink: 0;
img {
width: 100%;
height: 100%;
}
}
.card-item-text {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 7px;
.card-item-title {
color: rgb(59, 65, 75);
font-family: "Source Han Sans CN";
font-size: 18px;
font-weight: 700;
line-height: 22px;
display: inline-flex;
}
.card-item-time {
color: rgb(95, 101, 108);
font-family: "Source Han Sans CN";
font-size: 14px;
font-weight: 400;
line-height: 22px;
text-align: left;
display: inline-flex;
.card-open-image {
width: 16px;
height: 16px;
margin-left: 9px;
margin-top: 3px;
img {
width: 100%;
height: 100%;
}
}
}
}
.card-item-category {
gap: 8px;
height: 24px;
display: flex;
overflow: hidden;
white-space: nowrap;
}
.tag-box {
display: flex;
gap: 8px;
.tag {
height: 22px;
padding: 0 8px;
box-sizing: border-box;
border: 1px solid rgba(230, 231, 232, 1);
border-radius: 4px;
background: rgba(247, 248, 249, 1);
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
}
.file-box {
display: flex;
gap: 8px;
.file {
height: 32px;
display: flex;
justify-content: center;
align-items: center;
gap: 12px;
border-radius: 4px;
background: rgba(246, 250, 255, 1);
padding-left: 8px;
padding-right: 8px;
.type {
height: 22px;
padding: 0 4px;
border-radius: 4px;
background: rgba(231, 243, 255, 1);
color: rgba(5, 95, 194, 1);
font-family: "Source Han Sans CN";
font-size: 14px;
font-weight: 400;
line-height: 22px;
}
.title {
color: rgba(5, 95, 194, 1);
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
.more {
width: 20px;
height: 20px;
display: flex;
margin-top: 2px;
.img {
width: 100%;
height: 100%;
}
}
}
}
}
.right-footer {
margin-top: 43px;
display: flex;
justify-content: space-between;
.info {
height: 19px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 18px;
letter-spacing: 0px;
text-align: left;
}
}
}
}
.divider {
height: 1px;
background: rgb(234, 236, 238);
margin: 16px 0;
}
</style>
......@@ -13,13 +13,8 @@
</div> -->
<div class="home-main-header-center">
<SearchContainer
style="margin-bottom: 0; margin-top: 51px; height: fit-content"
v-if="containerRef"
placeholder="搜索智库报告"
:containerRef="containerRef"
areaName="智库"
/>
<SearchContainer class="think-tank-search" style="margin-bottom: 0; margin-top: 51px; height: fit-content;"
v-if="containerRef" placeholder="搜索智库、报告或政策建议" :containerRef="containerRef" areaName="智库" />
<!-- <el-input v-model="searchThinktankText" @keyup.enter="handleSearch"
style="width: 838px; height: 100%" placeholder="搜索智库报告" />
<div class="search">
......@@ -57,8 +52,10 @@
<!-- <div class="rank" :class="{ rank1: item.rank === 1, rank2: item.rank === 2, rank3: item.rank === 3 }">
{{ "No." + (index + 1) }}
</div> -->
<div class="rank">
{{ item.reportNumber + "篇报告" }}
<div class="rank"
:class="{ 'rank-number-one': index === 0, 'rank-number-two': index === 1, 'rank-number-three': index === 2, 'rank-number-four': index === 3, 'rank-number-five': index === 4 }">
<div class="number"> {{ "No." + (index + 1) }}</div>
</div>
</div>
<div class="card-title">
......@@ -103,18 +100,14 @@
<div class="icon">
<img src="./assets/images/box1-header-icon.png" alt="" />
</div>
<div class="title">{{ "智库发布" }}</div>
<div class="title-box">
<div class="title">{{ "智库发布" }}</div>
</div>
</div>
<div class="box1-header-right" @click="handleClickToDetail">查看详情 ></div>
</div>
<el-carousel
ref="carouselRef"
height="395px"
:autoplay="true"
:interval="3000"
arrow="never"
indicator-position="none"
>
<el-carousel ref="carouselRef" height="395px" :autoplay="true" :interval="3000" arrow="never"
indicator-position="none">
<el-carousel-item v-for="(itemData, index) in box1Data" :key="index">
<div class="box1-main">
<div class="box1-main-left">
......@@ -122,25 +115,26 @@
</div>
<div class="box1-main-right">
<div class="title">{{ itemData?.reportName }}</div>
<div class="tag-box">
<!-- <div class="tag" v-for="(item, index) in itemData?.industryVOList" :key="index">
{{ item.industryName }}
</div> -->
<AreaTag
v-for="(item, index) in itemData?.industryVOList"
:key="index"
:tagName="item.industryName"
></AreaTag>
</div>
<div class="content">{{ itemData?.summary }}</div>
<div class="box1-right-footer">
<div class="time">{{ itemData?.time }}</div>
<div class="name">
<div class="name">
<div class="logo-title-box">
<div class="logo">
<img :src="itemData?.thinkTankImage" alt="" />
</div>
<div class="text">{{ itemData?.thinkTankName }}</div>
<div class="text">{{ itemData?.reportDate }}</div>
<div class="title">{{ itemData?.thinkTankName + " · " + "智库报告" }}</div>
</div>
<div class="time">{{ itemData?.reportDate }}</div>
</div>
<div class="content">{{ itemData?.summary }}</div>
<div class="box1-right-footer">
<div class="tag-box">
<!-- <div class="tag" v-for="(item, index) in itemData?.industryVOList" :key="index">
{{ item.industryName }}
</div> -->
<AreaTag v-for="(item, index) in itemData?.industryVOList" :key="index"
:tagName="item.industryName">
</AreaTag>
</div>
</div>
</div>
......@@ -148,34 +142,15 @@
</el-carousel-item>
</el-carousel>
</div>
<RiskSignal
:list="warningList"
@more-click="handleToMoreRiskSignal"
postDate="time"
name="title"
@item-click="handleClickToDetail"
/>
<RiskSignal :list="warningList" @more-click="handleToMoreRiskSignal" postDate="time" name="title"
@item-click="handleClickToDetail" />
</div>
<DivideHeader id="position2" class="divide-header" :titleText="'资讯要闻'"></DivideHeader>
<div class="center-center">
<NewsList
:newsList="newsList"
@item-click="handleToNewsAnalysis"
@more-click="handleToMoreNews"
img="newsImage"
title="newsTitle"
content="newsContent"
from="from"
/>
<MessageBubble
:messageList="messageList"
imageUrl="personImage"
@more-click="handleToSocialDetail"
@person-click="handleClickPerson"
name="personName"
content="remarks"
source="orgName"
/>
<NewsList :newsList="newsList" @item-click="handleToNewsAnalysis" @more-click="handleToMoreNews"
img="newsImage" title="newsTitle" content="newsContent" from="from" />
<MessageBubble :messageList="messageList" imageUrl="personImage" @more-click="handleToSocialDetail"
@person-click="handleClickPerson" name="personName" content="remarks" source="orgName" />
</div>
<DivideHeader id="position3" class="divide-header" :titleText="'数据总览'"></DivideHeader>
<div class="center-footer">
......@@ -189,17 +164,18 @@
</div>
<div class="box5-select-box">
<el-select v-model="box5selectetedMonths" placeholder="选择时间" style="width: 120px">
<el-option
v-for="item in box5MonthsList"
:key="item.value"
:label="item.label"
:value="item.value"
@click="changeBox5Data(item.value)"
/>
<el-option v-for="item in box5MonthsList" :key="item.value" :label="item.label" :value="item.value"
@click="changeBox5Data(item.value)" />
</el-select>
</div>
</div>
<div class="box5-main" id="box5Chart"></div>
<div class="box5-main">
<div id="box5Chart"></div>
<div class="source">
<div class="info"><img src="./assets/images/image-exclamation.png"></div>
<div class="text"> 数据来源:美国国会官网,数据时间:2015.1至2025.12</div>
</div>
</div>
</div>
<div class="box6">
<div class="box6-header">
......@@ -209,17 +185,18 @@
<div class="header-title">{{ "政策建议领域分布" }}</div>
<div class="box6-select-box">
<el-select v-model="box6selectetedYear" placeholder="选择时间" style="width: 120px">
<el-option
v-for="item in box6YearList"
:key="item.value"
:label="item.label"
:value="item.value"
@click="handleBox6()"
/>
<el-option v-for="item in box6YearList" :key="item.value" :label="item.label" :value="item.value"
@click="handleBox6()" />
</el-select>
</div>
</div>
<div class="box6-main" id="box6Chart"></div>
<div class="box6-main">
<div id="box6Chart"></div>
<div class="source">
<div class="info"><img src="./assets/images/image-exclamation.png"></div>
<div class="text"> 数据来源:美国国会官网,数据时间:2015.1至2025.12</div>
</div>
</div>
</div>
</div>
<div class="center-footer1">
......@@ -244,36 +221,28 @@
</div>
<div class="box8-select-box">
<el-select v-model="box8selectetedYear" placeholder="选择时间" style="width: 120px">
<el-option
v-for="item in box8YearList"
:key="item.value"
:label="item.label"
:value="item.value"
@click="changeBox8Data(item.value)"
/>
<el-option v-for="item in box8YearList" :key="item.value" :label="item.label" :value="item.value"
@click="changeBox8Data(item.value)" />
</el-select>
</div>
</div>
<div class="box8-main">
<div class="box8-item" v-for="(item, index) in box8Data" :key="index">
<div
class="item-left"
:class="{ itemBold1: index === 0, itemBold2: index === 1, itemBold3: index === 2 }"
>
<div class="item-left"
:class="{ itemBold1: index === 0, itemBold2: index === 1, itemBold3: index === 2 }">
{{ index + 1 }}
</div>
<!-- <el-popover effect="dark" :content="item.clause" placement="top-start">
<template #reference> -->
<div
class="item-center"
:class="{ itemBold1: index === 0, itemBold2: index === 1, itemBold3: index === 2 }"
>
<div class="item-center"
:class="{ itemBold1: index === 0, itemBold2: index === 1, itemBold3: index === 2 }">
{{ item.clause }}
</div>
<!-- </template>
</el-popover> -->
<!-- <div class="item-right">{{ `${item.count}份报告 >` }}</div> -->
<div class="item-count">{{ item.count + "份报告 >" }}</div>
</div>
</div>
</div>
......@@ -285,25 +254,20 @@
<div class="home-main-footer-header">
<div class="btn-box">
<div
class="btn"
:class="{ btnActive: activeCate === cate }"
v-for="(cate, index) in categoryList"
:key="index"
@click="handleClickCate(cate)"
>
<div class="btn" :class="{ btnActive: activeCate === cate }" v-for="(cate, index) in categoryList"
:key="index" @click="handleClickCate(cate)">
{{ cate }}
</div>
</div>
<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-if="activeSort" 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-if="activeSort" src="@/assets/icons/shengxu2.png" alt="" />
<img v-else src="@/assets/icons/jiangxu2.png" alt="" />
</div>
</div>
......@@ -313,108 +277,34 @@
<el-option @click="handleGetetThinkTankReport()" :key="false" label="倒序" :value="false" />
</el-select> -->
</div>
<div class="home-main-footer-main">
<div class="left">
<div class="select-box">
<div class="header">
<div class="icon"></div>
<div class="title">{{ "科技领域" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox
v-model="checkAll"
:indeterminate="isIndeterminate"
class="all-checkbox"
@change="handleCheckAllChange"
>
全部领域
</el-checkbox>
<el-checkbox
v-for="research in areaList"
:key="research.id"
v-model="selectedAreaList"
:label="research.id"
@change="handleCheckedAreaChange()"
class="filter-checkbox"
>
{{ research.name }}
</el-checkbox>
</div>
</div>
</div>
<div class="select-box">
<div class="header">
<div class="icon"></div>
<div class="title">{{ "发布时间" }}</div>
</div>
<div class="select-main">
<div class="checkbox-group">
<el-checkbox
v-model="checkAllTime"
class="all-checkbox"
:indeterminate="isIndeterminateTime"
@change="handleCheckAllChangeTime"
>
全部时间
</el-checkbox>
<el-checkbox-group v-model="selectedPubTimeList">
<el-checkbox
v-for="time in pubTimeList"
:key="time.id"
:label="time.id"
class="filter-checkbox"
@change="handleCheckedAreaChangeTime()"
>
{{ time.name }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
</div>
</div>
<div class="right">
<div class="card-box">
<div
class="footer-card"
v-for="(item, index) in curFooterList"
:key="index"
@click="handleToReportDetail(item)"
>
<div class="footer-card-top">
<img :src="item.imageUrl" alt="" />
</div>
<!-- <el-popover effect="dark" :content="item.name" placement="top-start">
<template #reference>
<div class="footer-card-title">
{{ item.name }}
</div>
</template>
</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>
</div>
</div>
</div>
<div class="right-footer">
<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"
/>
</div>
</div>
</div>
<div class="resource-library-content">
<HomeMainFooterMain v-if="activeCate === '智库报告'" v-model:checkAll="checkAll"
:is-indeterminate="isIndeterminate" :area-list="areaList" v-model:selectedAreaList="selectedAreaList"
@check-all-change="handleCheckAllChange" @checked-area-change="handleCheckedAreaChange()"
v-model:checkAllTime="checkAllTime" :is-indeterminate-time="isIndeterminateTime"
:pub-time-list="pubTimeList" v-model:selectedPubTimeList="selectedPubTimeList"
@check-all-time-change="handleCheckAllChangeTime" @checked-area-time-change="handleCheckedAreaChangeTime()"
:cur-footer-list="curFooterList" :total="total" :current-page="currentPage"
@report-click="handleToReportDetail" @page-change="handleCurrentChange" />
<HomeMainFooterSurvey v-else-if="activeCate === '调查项目'" v-model:checkAll="surveyCheckAll"
:is-indeterminate="surveyIsIndeterminate" :area-list="areaList"
v-model:selectedAreaList="surveySelectedAreaList" @check-all-change="handleSurveyCheckAllChange"
@checked-area-change="handleSurveyCheckedAreaChange()" v-model:checkAllTime="surveyCheckAllTime"
:is-indeterminate-time="surveyIsIndeterminateTime" :pub-time-list="pubTimeList"
v-model:selectedPubTimeList="surveySelectedPubTimeList"
@check-all-time-change="handleSurveyCheckAllChangeTime"
@checked-area-time-change="handleSurveyCheckedAreaChangeTime()" :cur-footer-list="surveyFooterList"
:total="surveyTotal" :current-page="surveyCurrentPage" @report-click="handleToReportDetail"
@page-change="handleSurveyCurrentChange" />
<ThinkTankCongressHearingOverview v-else-if="activeCate === '国会听证会'" :key="`congress-${resourceTabResetKey}`"
:research-type-list="areaList" :research-time-list="pubTimeList" @report-click="handleToReportDetail" />
<ThinkTankPolicyAdviceOverview v-else :key="`policy-${resourceTabResetKey}`" :research-type-list="areaList"
:research-time-list="pubTimeList" :list="policyFooterList" :total="policyTotal"
:current-page="policyCurrentPage" :page-size="7" @filter-change="handlePolicyFilterChange"
@page-change="handlePolicyCurrentChange" />
</div>
</div>
</div>
......@@ -422,13 +312,18 @@
</template>
<script setup>
import RiskSignal from "@/components/base/RiskSignal/index.vue";
import NewsList from "@/components/base/NewsList/index.vue";
import RiskSignal from "@/components/base/riskSignal/index.vue";
import NewsList from "@/components/base/newsList/index.vue";
import MessageBubble from "@/components/base/MessageBubble/index.vue"
import { onMounted, ref, computed, reactive, nextTick } from "vue";
import scrollToTop from "@/utils/scrollToTop";
import router from "@/router";
import DivideHeader from "@/components/DivideHeader.vue";
import setChart from "@/utils/setChart";
import HomeMainFooterMain from "./components/HomeMainFooterMain.vue";
import HomeMainFooterSurvey from "./components/HomeMainFooterSurvey.vue";
import ThinkTankCongressHearingOverview from "./components/ThinkTankCongressHearingOverview.vue";
import ThinkTankPolicyAdviceOverview from "./components/ThinkTankPolicyAdviceOverview.vue";
import {
getThinkTankList,
......@@ -440,6 +335,7 @@ import {
getNewReport,
getHylyList,
getThinkTankReport,
getThinkTankOverviewPolicy,
getThinkTankReportNews,
getThinkTankReportRemarks
} from "@/api/thinkTank/overview";
......@@ -483,7 +379,33 @@ import Box1Logo from "./assets/images/box1-logo.png";
import { setCanvasCreator } from "echarts/core";
import { ElMessage } from "element-plus";
const containerRef = ref(null);
const statCountInfo = ref([]);
const getStatCountInfo = async () => {
// console.log('----getStatCountInfo', res.data)
statCountInfo.value = [
{
name: "追踪智库数量",
count: "1"
},
{
name: "本月新增报告",
count: "2"
},
{
name: "重点政策建议",
count: "2"
},
{
name: "热点科技领域",
count: "2"
}
];
};
const searchThinktankText = ref(""); //搜索科技人物及观点
// 智库列表
const cardList = ref([
......@@ -565,7 +487,18 @@ const handleGetNewReport = async () => {
const res = await getNewReport();
console.log("智库发布", res);
if (res.code === 200 && res.data) {
box1Data.value = res.data;
box1Data.value = res.data.map(item => {
const formatDate = (dateStr) => {
if (!dateStr) return ''; // 处理空值,避免报错
const [year, month, day] = dateStr.split('-');
return `${year}${parseInt(month, 10)}${parseInt(day, 10)}日`;
};
return {
...item,
reportDate: formatDate(item.reportDate)
}
})
}
} catch (error) {
console.error("获取智库列表error", error);
......@@ -767,7 +700,8 @@ const handleGetThinkTankReportRemarks = async () => {
const res = await getThinkTankReportRemarks();
console.log("智库人物动态", res);
if (res.code === 200 && res.data) {
messageList.value = res.data;
// 只展示后端返回的前三条
messageList.value = (res.data || []).slice(0, 3);
messageList.value.forEach(item => {
item.time = item.time.replace("T", " ");
});
......@@ -954,7 +888,8 @@ function transformToChartFormat(data) {
// 预设颜色池(可按需修改或扩展)
const colorPalette = ["#4096FF", "#FFA39E", "#ADC6FF", "#FFC069", "#B5F5EC", "#B37FEB", "#D6E4FF", "#FF8C8C", "#87E8DE"];
return data.map((item, index) => ({
const list = Array.isArray(data) ? data.slice(0, 7) : [];
return list.map((item, index) => ({
name: item.industry,
value: item.amount,
color: colorPalette[index % colorPalette.length]
......@@ -1190,10 +1125,71 @@ const handleGetThinkTankHot = async date => {
};
// 资源库
const categoryList = ref(["智库报告", "政策建议"]);
const categoryList = ref(["智库报告", "调查项目", "国会听证会", "政策建议"]);
const activeCate = ref("智库报告");
const resourceTabResetKey = ref(0)
const resetResourceTabCommon = () => {
// 统一回到“刷新后刚加载出来的状态”
// 分页归 1,排序归默认(false)
currentPage.value = 1
sort.value = false
surveyCurrentPage.value = 1
surveySort.value = false
policyCurrentPage.value = 1
policySort.value = false
// 强制重置那些在子组件内部维护状态的组件(国会听证会/政策建议筛选)
resourceTabResetKey.value += 1
}
const resetThinkTankReportFilters = () => {
checkAll.value = false
isIndeterminate.value = true
selectedAreaList.value = []
checkAllTime.value = false
isIndeterminateTime.value = true
selectedPubTimeList.value = [""]
}
const resetSurveyFilters = () => {
surveyCheckAll.value = false
surveyIsIndeterminate.value = true
surveySelectedAreaList.value = []
surveyCheckAllTime.value = false
surveyIsIndeterminateTime.value = true
surveySelectedPubTimeList.value = [""]
}
const resetPolicyFilters = () => {
// 默认“不过滤领域”:domainIds 传 null,由后端返回全部领域
policySelectedTypeIds.value = []
// 默认选择最新一年,保证 /thinkTankOverview/policy 能返回数据(后端通常需要 years)
policySelectedYearIds.value = pubTimeList.value?.length ? [pubTimeList.value[0].id] : []
}
const handleClickCate = cate => {
activeCate.value = cate;
// 切换到不同分类时,触发对应数据加载,且互不影响
if (cate === "智库报告") {
resetResourceTabCommon()
resetThinkTankReportFilters()
handleGetetThinkTankReport();
} else if (cate === "调查项目") {
resetResourceTabCommon()
resetSurveyFilters()
handleGetThinkTankSurvey();
} else if (cate === "政策建议") {
resetResourceTabCommon()
resetPolicyFilters()
handleGetThinkTankPolicyAdvice();
} else if (cate === "国会听证会") {
resetResourceTabCommon()
}
};
const areaList = ref([
......@@ -1286,9 +1282,25 @@ const selectedPubTimeList = ref([""]);
const checkAllTime = ref(false);
const isIndeterminateTime = ref(true);
const sort = ref(false);
const activeSort = computed(() => {
if (activeCate.value === "调查项目") return surveySort.value;
if (activeCate.value === "政策建议") return policySort.value;
// 国会听证会目前不走排序;默认使用智库报告排序状态
return sort.value;
});
const handleSwithSort = () => {
if (activeCate.value === "调查项目") {
surveySort.value = !surveySort.value;
handleGetThinkTankSurvey();
return;
}
if (activeCate.value === "政策建议") {
policySort.value = !policySort.value;
handleGetThinkTankPolicyAdvice();
return;
}
sort.value = !sort.value;
handleGetetThinkTankReport()();
handleGetetThinkTankReport();
};
const handleCheckAllChangeTime = val => {
......@@ -1390,6 +1402,190 @@ const curFooterList = ref([
]);
const currentPage = ref(1);
const total = ref(0);
// ===== 调查项目:独立状态(不影响智库报告)=====
const surveyCheckAll = ref(false);
const surveyIsIndeterminate = ref(true);
const surveySelectedAreaList = ref([]);
const surveySelectedPubTimeList = ref([""]);
const surveyCheckAllTime = ref(false);
const surveyIsIndeterminateTime = ref(true);
const surveySort = ref(false);
const surveyFooterList = ref([]);
const surveyCurrentPage = ref(1);
const surveyTotal = ref(0);
const handleSurveyCheckAllChange = val => {
if (val) {
surveyIsIndeterminate.value = false;
surveySelectedAreaList.value.length !== areaList.value.length
? (surveySelectedAreaList.value = areaList.value.map(obj => obj.id))
: "";
} else {
surveySelectedAreaList.value = [];
}
handleGetThinkTankSurvey();
};
const handleSurveyCheckedAreaChange = () => {
surveySelectedAreaList.value.length !== areaList.value.length
? (surveyIsIndeterminate.value = true)
: ((surveyCheckAll.value = true), (surveyIsIndeterminate.value = false));
handleGetThinkTankSurvey();
};
const handleSurveyCheckAllChangeTime = val => {
if (val) {
surveyIsIndeterminateTime.value = false;
surveySelectedPubTimeList.value.length !== pubTimeList.value.length
? (surveySelectedPubTimeList.value = pubTimeList.value.map(obj => obj.id))
: "";
} else {
surveySelectedPubTimeList.value = [];
}
handleGetThinkTankSurvey();
};
const handleSurveyCheckedAreaChangeTime = () => {
surveySelectedPubTimeList.value.length !== pubTimeList.value.length
? (surveyIsIndeterminateTime.value = true)
: ((surveyCheckAllTime.value = true), (surveyIsIndeterminateTime.value = false));
handleGetThinkTankSurvey();
};
const handleSurveyCurrentChange = page => {
surveyCurrentPage.value = page;
handleGetThinkTankSurvey();
};
const handleGetThinkTankSurvey = async () => {
const params = {
currentPage: surveyCurrentPage.value - 1,
pageSize: 12,
sortFun: surveySort.value,
researchTypeIds: arrayToString(surveySelectedAreaList.value),
years: arrayToString(surveySelectedPubTimeList.value),
category: "调查项目"
};
try {
const res = await getThinkTankReport(params);
if (res.code === 200 && res.data) {
surveyFooterList.value = res.data.content;
surveyTotal.value = res.data.totalElements;
} else {
surveyFooterList.value = [];
surveyTotal.value = 0;
}
} catch (error) {
console.error("获取调查项目 error", error);
}
};
// ===== 政策建议:独立状态(不影响智库报告/调查项目)=====
const policyFooterList = ref([]);
const policyCurrentPage = ref(1);
const policyTotal = ref(0);
const policySort = ref(false);
const policySelectedTypeIds = ref([]);
const policySelectedYearIds = ref([]);
const handlePolicyFilterChange = payload => {
policySelectedTypeIds.value = payload?.researchTypeIds ? [...payload.researchTypeIds] : [];
policySelectedYearIds.value = payload?.researchTimeIds ? [...payload.researchTimeIds] : [];
policyCurrentPage.value = 1;
handleGetThinkTankPolicyAdvice();
};
const handlePolicyCurrentChange = page => {
policyCurrentPage.value = page;
handleGetThinkTankPolicyAdvice();
};
const handleGetThinkTankPolicyAdvice = async () => {
const mockPolicyAdviceList = () => ([
{
id: 23702,
content: "研究未来AI数据中心电力需求与供应",
imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg",
name: "指数级增长下AI的电力需求:外推AI数据中心的电力需求并评估其对美国竞争力的潜在影响",
reportId: "Rand_RRA3572-1",
tagList: ["新能源", "人工智能"],
thinkTankName: null,
times: "2025-12-28"
},
{ id: 23703, content: "构建可信任的AI治理框架:监管与创新的平衡", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "AI治理路线图:从风险评估到合规落地的实践建议", reportId: "Rand_RRA3572-2", tagList: ["人工智能", "网络安全"], thinkTankName: null, times: "2025-12-21" },
{ id: 23704, content: "先进制造供应链韧性评估与关键节点识别", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "供应链韧性:关键材料、关键设备与关键人才的系统性策略", reportId: "Rand_RRA3572-3", tagList: ["先进制造", "新材料"], thinkTankName: null, times: "2025-12-14" },
{ id: 23705, content: "半导体出口管制对产业生态的中长期影响", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "出口管制与产业政策:如何降低对关键环节的外部依赖", reportId: "Rand_RRA3572-4", tagList: ["集成电路", "先进制造"], thinkTankName: null, times: "2025-12-07" },
{ id: 23706, content: "量子信息技术发展态势与应用落地路径", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "量子科技:从基础研究到产业化的阶段性里程碑", reportId: "Rand_RRA3572-5", tagList: ["量子科技", "前沿基础"], thinkTankName: null, times: "2025-11-30" },
{ id: 23707, content: "网络安全威胁图谱:关键基础设施的攻击面", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "关键基础设施安全:供应链、身份与数据的三重防护", reportId: "Rand_RRA3572-6", tagList: ["网络安全", "数据安全"], thinkTankName: null, times: "2025-11-23" },
{ id: 23708, content: "生物技术与医疗创新的监管协同机制", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "生物科技创新:试验、审批与产业化的全流程政策工具箱", reportId: "Rand_RRA3572-7", tagList: ["生物科技", "医疗健康"], thinkTankName: null, times: "2025-11-16" },
{ id: 23709, content: "清洁能源转型下的电网规划与储能配置", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "能源系统转型:电网升级、储能布局与成本测算", reportId: "Rand_RRA3572-8", tagList: ["新能源", "储能"], thinkTankName: null, times: "2025-11-09" },
{ id: 23710, content: "新材料在国防与先进制造中的应用瓶颈", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "关键新材料:验证体系、规模化与供应链安全", reportId: "Rand_RRA3572-9", tagList: ["新材料", "先进制造"], thinkTankName: null, times: "2025-11-02" },
{ id: 23711, content: "通信网络演进:6G 与卫星互联网的融合", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "下一代通信:频谱、标准与产业联盟策略", reportId: "Rand_RRA3572-10", tagList: ["通信网络", "卫星互联网"], thinkTankName: null, times: "2025-10-26" },
{ id: 23712, content: "数据要素市场建设与跨境数据合规路径", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "数据治理与合规:分类分级、出境评估与执法协同", reportId: "Rand_RRA3572-11", tagList: ["数据安全", "数字治理"], thinkTankName: null, times: "2025-10-19" },
{ id: 23713, content: "AI 研发人才供需缺口与教育体系对接", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "AI 人才战略:培养、引进与留用的组合政策", reportId: "Rand_RRA3572-12", tagList: ["人工智能", "人才政策"], thinkTankName: null, times: "2025-10-12" },
{ id: 23714, content: "自动驾驶安全监管与测试评价体系", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "自动驾驶:安全标准、责任划分与道路试点机制", reportId: "Rand_RRA3572-13", tagList: ["智能网联", "交通出行"], thinkTankName: null, times: "2025-10-05" },
{ id: 23715, content: "关键基础设施数字化升级的投融资机制", imageUrl: "https://www.rand.org/content/rand/pubs/research_reports/RRA3572-1/jcr:content/par/teaser.crop.1200x900.cm.jpeg/1738160125961.jpeg", name: "基础设施升级:公共资金撬动与绩效评估体系", reportId: "Rand_RRA3572-14", tagList: ["数字化转型", "基础设施"], thinkTankName: null, times: "2025-09-28" }
]);
const applyMockPolicyAdvice = () => {
const mock = mockPolicyAdviceList();
policyTotal.value = mock.length;
const pageSize = 7;
const page = Math.max(1, Number(policyCurrentPage.value) || 1);
const start = (page - 1) * pageSize;
policyFooterList.value = mock.slice(start, start + pageSize);
};
const fallbackYear = pubTimeList.value?.length ? String(pubTimeList.value[0].id) : null
const yearsStr = arrayToString(policySelectedYearIds.value)
// 领域:如果用户还没选领域,则默认使用“全部领域”的 id 列表
const effectiveDomainIds = policySelectedTypeIds.value.length
? policySelectedTypeIds.value
: (areaList.value || []).map(obj => obj.id)
const domainIdsStr = arrayToString(effectiveDomainIds)
const params = {
currentPage: policyCurrentPage.value - 1,
pageSize: 7,
sortFun: policySort.value,
years: yearsStr === "" ? fallbackYear : yearsStr
};
// 领域:始终传 domainIds;如果用户没选,就传“全部领域”的 id 串
params.domainIds = domainIdsStr || null
try {
const res = await getThinkTankOverviewPolicy(params);
if (res.code === 200 && res.data) {
// /thinkTankOverview/policy 返回:data.content[{id,title,content,date,coverImage,domains,...}]
const mapped = (res.data.content || []).map(item => ({
// 兼容你需要的结构(更接近政策追踪)
id: item.id,
content: item.content,
name: item.title,
reportName: item.reportName,
times: item.date,
imageUrl: item.coverImage,
tagList: item.domains || [],
thinkTankName: item.thinkTankName ?? null,
reportId: item.reportId ?? item.id,
// 保留原字段备用
billInfoList: item.billInfoList,
administrativeOrderInfoVOList: item.administrativeOrderInfoVOList
}));
if (!mapped.length) {
applyMockPolicyAdvice();
return;
}
policyFooterList.value = mapped;
policyTotal.value = res.data.totalElements || mapped.length;
} else {
applyMockPolicyAdvice();
}
} catch (error) {
applyMockPolicyAdvice();
console.error("获取政策建议 error", error);
}
};
// 处理页码改变事件
const handleCurrentChange = page => {
console.log(page, "pagepagepage");
......@@ -1504,7 +1700,7 @@ const handleClickPerson = async item => {
ElMessage.warning("找不到当前人员的类型值!");
return;
}
} catch (error) {}
} catch (error) { }
};
// 点击新闻条目,跳转到新闻分析页
......@@ -1543,6 +1739,7 @@ const handleSearch = () => {
onMounted(async () => {
handleGetThinkTankList();
await getStatCountInfo();
// 定义一个定时器,每隔2秒轮播一次
setInterval(() => {
// 索引加1
......@@ -1600,6 +1797,11 @@ onMounted(async () => {
padding: 1px;
position: relative;
.think-tank-search :deep(::placeholder) {
font-size: 20px !important;
/* !important 确保优先级高于子组件原有样式 */
}
&:hover {
border: 1px solid var(--color-main-active);
}
......@@ -1809,9 +2011,10 @@ onMounted(async () => {
.home-main-header-card-box {
margin-top: 64px;
width: 1600px;
display: flex;
justify-content: space-between;
gap: 16px;
.card {
width: 253px;
......@@ -1849,20 +2052,61 @@ onMounted(async () => {
.rank {
width: 100px;
height: 32px;
line-height: 32px;
text-align: center;
.number {
line-height: 32px;
text-align: left;
font-family: "YouSheBiaoTiHei";
font-size: 24px;
font-weight: 400;
line-height: 31px;
letter-spacing: 0px;
overflow: hidden;
height: 31px;
}
}
// text-overflow: ellipsis;
// white-space: nowrap;
.rank-number-one {
background: linear-gradient(90deg, rgba(206, 79, 81, 0), rgba(206, 79, 81, 0.3) 100%);
color: rgb(206, 79, 81);
padding-left: 33px;
}
.rank-number-two {
background: linear-gradient(270deg, rgba(255, 172, 77, 0.3), rgba(255, 172, 77, 0) 100%);
color: rgb(255, 149, 77);
padding-left: 23px;
}
.rank-number-three {
background: linear-gradient(270deg, rgba(255, 197, 61, 0.3), rgba(255, 197, 61, 0) 100%);
color: rgba(255, 197, 61, 1);
padding-left: 23px;
}
.rank-number-four {
background: linear-gradient(270deg, rgba(10, 87, 166, 0.3), rgba(10, 87, 166, 0) 100%);
color: rgba(5, 95, 194, 1);
font-family: YouSheBiaoTiHei;
font-size: 24px;
font-weight: 400;
line-height: 32px;
letter-spacing: 0px;
overflow: hidden;
// text-overflow: ellipsis;
// white-space: nowrap;
padding-left: 23px;
}
.rank-number-five {
background: linear-gradient(270deg, rgba(10, 87, 166, 0.3), rgba(10, 87, 166, 0) 100%);
color: rgba(5, 95, 194, 1);
padding-left: 23px;
}
.rank1 {
background: linear-gradient(270deg, rgba(206, 79, 81, 0.3), rgba(206, 79, 81, 0) 100%);
color: rgba(206, 79, 81, 1);
......@@ -1887,10 +2131,10 @@ onMounted(async () => {
justify-content: space-between;
.title-left {
width: 175px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 700;
line-height: 24px;
......@@ -1901,21 +2145,24 @@ onMounted(async () => {
.title-right {
height: 22px;
color: rgba(132, 136, 142, 1);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: right;
margin-top: 1px;
}
}
.content {
margin: 13px auto 19px;
margin-left: 20px;
margin-top: 13px;
margin-bottom: 18px;
width: 212px;
height: 66px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 14px;
font-weight: 400;
line-height: 22px;
......@@ -1929,11 +2176,12 @@ onMounted(async () => {
}
.tag-box {
margin: 0 20px;
margin-left: 20px;
margin-right: 21px;
margin-bottom: 21px;
display: flex;
gap: 8px;
height: 25px;
margin: 0 20px;
height: 24px;
display: flex;
flex-wrap: wrap;
/* 允许换行 */
......@@ -2019,22 +2267,22 @@ onMounted(async () => {
}
.home-main-center {
margin-top: 34px;
.center-top {
height: 450px;
display: flex;
justify-content: center;
gap: 20px;
gap: 16px;
.box1 {
width: 1064px;
width: 1063px;
height: 450px;
box-shadow: 0px 0px 15px 0px rgba(22, 119, 255, 0.1);
box-shadow: 0px 0px 20px 0px rgba(22, 69, 130, 0.1);
background: #fff;
box-sizing: border-box;
border-radius: 10px;
position: relative;
border: 1px solid rgb(234, 236, 238);
.box1-left {
position: absolute;
......@@ -2076,10 +2324,10 @@ onMounted(async () => {
display: flex;
.icon {
width: 18px;
height: 18px;
margin-left: 19px;
margin-top: 16px;
width: 24px;
height: 24px;
margin-left: 17px;
margin-top: 11px;
img {
width: 100%;
......@@ -2087,35 +2335,49 @@ onMounted(async () => {
}
}
.title {
.title-box {
width: 112px;
height: 48px;
margin-left: 25px;
color: #fff;
margin-left: 19px;
background: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 700;
line-height: 48px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
.title {
color: rgb(255, 255, 255);
font-family: "Source Han Sans CN";
font-size: 20px;
font-weight: 700;
line-height: 26px;
text-align: left;
letter-spacing: 0;
width: 80px;
height: 26px;
}
}
}
.box1-header-right {
margin-top: 16px;
margin-top: 12px;
height: 16px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 400;
line-height: 16px;
cursor: pointer;
margin-right: 39px;
margin-right: 27px;
letter-spacing: 0;
}
}
.box1-main {
margin: 24px auto;
margin-top: 24px;
margin-left: 62px;
width: 948px;
height: 353px;
display: flex;
......@@ -2138,14 +2400,15 @@ onMounted(async () => {
.title {
width: 462px;
max-height: 52px;
height: 52px;
overflow: hidden;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 20px;
font-weight: 700;
line-height: 26px;
letter-spacing: 0px;
text-align: left;
text-align: justify;
}
.tag-box {
......@@ -2173,68 +2436,79 @@ onMounted(async () => {
}
}
.content {
margin-top: 17px;
width: 462px;
height: 183px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
display: -webkit-box;
-webkit-line-clamp: 6;
/* 限制行数为5 */
-webkit-box-orient: vertical;
overflow: hidden;
}
.box1-right-footer {
margin-top: 31px;
.name {
display: flex;
height: 24px;
margin-top: 22px;
justify-content: space-between;
.time {
.logo-title-box {
display: flex;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
width: 211px;
.name {
display: flex;
justify-content: flex-end;
gap: 6px;
height: 36px;
.logo {
width: 36px;
height: 36px;
width: 16px;
height: 16px;
margin-top: 5px;
flex: 0 0 16px;
margin-right: 6px;
img {
width: 100%;
height: 100%;
}
}
.text {
margin-top: 6px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
.title {
color: rgb(59, 65, 75);
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: right;
text-align: left;
}
}
.time {
height: 24px;
color: rgb(59, 65, 75);
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
}
.content {
width: 462px;
height: 187px;
margin-top: 22px;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 6;
line-height: 30px;
word-break: break-all;
color: rgb(59, 65, 75);
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 400;
letter-spacing: 0px;
text-align: left;
}
}
}
......@@ -2426,6 +2700,7 @@ onMounted(async () => {
.center-center {
margin-top: 21px;
gap: 20px;
height: 450px;
display: flex;
justify-content: center;
......@@ -2566,7 +2841,7 @@ onMounted(async () => {
}
.box4 {
margin-left: 20px;
margin-left: 16px;
width: 792px;
height: 450px;
border-radius: 10px;
......@@ -2752,7 +3027,7 @@ onMounted(async () => {
}
.center-footer {
margin-top: 21px;
height: 460px;
display: flex;
justify-content: center;
......@@ -2768,7 +3043,7 @@ onMounted(async () => {
background: rgba(255, 255, 255, 1);
.box5-header {
height: 53px;
height: 48px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
margin: 0 auto;
display: flex;
......@@ -2781,7 +3056,8 @@ onMounted(async () => {
.box5-header-icon {
margin-top: 15px;
margin-left: 2px;
margin-left: 3px;
width: 19px;
height: 19px;
......@@ -2792,11 +3068,11 @@ onMounted(async () => {
}
.box5-header-title {
margin-top: 12px;
margin-left: 19px;
margin-top: 11px;
margin-left: 18px;
height: 26px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 20px;
font-weight: 700;
line-height: 26px;
......@@ -2807,13 +3083,55 @@ onMounted(async () => {
width: 120px;
height: 28px;
position: absolute;
top: 12px;
right: 25px;
top: 11px;
right: 31px;
}
}
.box5-main {
height: 397px;
height: 412px;
width: 1063px;
box-sizing: border-box;
#box5Chart {
height: 340px;
width: 1063px;
}
.source {
margin: 0 auto;
margin-top: 23px;
/* 上下0,左右自动居中 */
width: 370px;
height: 22px;
display: flex;
.info {
width: 16px;
height: 16px;
margin-top: 3px;
img {
width: 100%;
height: 100%;
}
}
.text {
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 14px;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
color: rgb(132, 136, 142);
margin-left: 8px;
}
}
}
}
......@@ -2828,7 +3146,7 @@ onMounted(async () => {
.box6-header {
width: 521px;
height: 53px;
height: 48px;
box-sizing: border-box;
padding: 0 20px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
......@@ -2836,7 +3154,8 @@ onMounted(async () => {
position: relative;
.header-icon {
margin-top: 18px;
margin-top: 15px;
margin-left: 3px;
width: 19px;
height: 19px;
......@@ -2847,14 +3166,14 @@ onMounted(async () => {
}
.header-title {
margin-top: 16px;
margin-left: 15px;
margin-top: 11px;
margin-left: 19px;
height: 22px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 20px;
font-weight: 700;
line-height: 22px;
line-height: 26px;
}
.box6-select-box {
......@@ -2867,9 +3186,53 @@ onMounted(async () => {
}
.box6-main {
margin: 5px 15px;
height: 395px;
width: 520px;
height: 412px;
box-sizing: border-box;
padding: 24px 24px 0;
#box6Chart {
width: 446px;
height: 309px;
}
.source {
margin: 0 auto;
margin-top: 23px;
/* 上下0,左右自动居中 */
width: 370px;
height: 22px;
display: flex;
.info {
width: 16px;
height: 16px;
margin-top: 3px;
img {
width: 100%;
height: 100%;
}
}
.text {
font-family: "Source Han Sans CN";
font-weight: 400;
font-size: 14px;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
color: rgb(132, 136, 142);
margin-left: 8px;
}
}
}
}
}
......@@ -2878,6 +3241,7 @@ onMounted(async () => {
display: flex;
justify-content: center;
gap: 15px;
margin-bottom: 36px;
.box7 {
width: 1064px;
......@@ -2889,7 +3253,7 @@ onMounted(async () => {
background: rgba(255, 255, 255, 1);
.box7-header {
height: 53px;
height: 48px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
margin: 0 auto;
display: flex;
......@@ -2902,7 +3266,7 @@ onMounted(async () => {
.box7-header-icon {
margin-top: 15px;
margin-left: 2px;
margin-left: 3px;
width: 19px;
height: 19px;
......@@ -2913,11 +3277,11 @@ onMounted(async () => {
}
.box7-header-title {
margin-top: 12px;
margin-top: 11px;
margin-left: 19px;
height: 26px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 20px;
font-weight: 700;
line-height: 26px;
......@@ -2959,6 +3323,8 @@ onMounted(async () => {
.box7-main {
height: 412px;
box-sizing: border-box;
padding: 24px 24px 0;
}
}
......@@ -2972,7 +3338,7 @@ onMounted(async () => {
background: rgba(255, 255, 255, 1);
.box8-header {
height: 53px;
height: 48px;
border-bottom: 1px solid rgba(240, 242, 244, 1);
margin: 0 auto;
display: flex;
......@@ -2985,7 +3351,7 @@ onMounted(async () => {
.box8-header-icon {
margin-top: 15px;
margin-left: 2px;
margin-left: 3px;
width: 19px;
height: 19px;
......@@ -2996,11 +3362,11 @@ onMounted(async () => {
}
.box8-header-title {
margin-top: 12px;
margin-top: 11px;
margin-left: 19px;
height: 26px;
color: rgba(20, 89, 187, 1);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 20px;
font-weight: 700;
line-height: 26px;
......@@ -3032,8 +3398,8 @@ onMounted(async () => {
.item-left {
width: 20px;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
color: rgb(95, 101, 108);
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 400;
line-height: 24px;
......@@ -3045,8 +3411,8 @@ onMounted(async () => {
margin-left: 20px;
width: 425px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
color: rgb(59, 65, 75);
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 400;
line-height: 24px;
......@@ -3057,6 +3423,14 @@ onMounted(async () => {
white-space: nowrap;
}
.item-count {
height: 24px;
width: 92px;
text-align: right;
font-family: "Source Han Sans CN";
color: rgb(95, 101, 108)
}
.itemBold1 {
color: rgba(206, 79, 81, 1);
font-weight: 700;
......@@ -3093,29 +3467,35 @@ onMounted(async () => {
.home-main-footer {
overflow: hidden;
background: rgba(247, 248, 249, 1);
height: 1700px;
.home-main-footer-header {
width: 1600px;
height: 42px;
margin: 36px auto;
margin: auto;
margin-bottom: 36px;
// background: orange;
display: flex;
justify-content: space-between;
.btn-box {
width: 1000px;
display: flex;
gap: 24px;
.btn {
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-family: "Source Han Sans CN";
font-size: 20px;
font-weight: 400;
line-height: 42px;
padding: 0 24px;
width: 150px;
height: 42px;
border-radius: 21px;
background: rgba(20, 89, 187, 0);
margin-right: 20px;
text-align: center;
cursor: pointer;
&:hover {
......@@ -3398,10 +3778,24 @@ onMounted(async () => {
}
}
/* 仅作用于智库概览页资源库下四个组件的选择框样式 */
.resource-library-content {
:deep(.el-checkbox__label) {
font-family: "Source Han Sans CN";
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0;
text-align: justify;
}
}
.divide-header {
margin: 0 auto;
margin-top: 52px;
margin-bottom: 36px;
margin-top: 64px;
margin-bottom: 30px;
}
.all-checkbox {
......@@ -3445,57 +3839,4 @@ onMounted(async () => {
text-align: left;
}
}
:deep(.el-pagination) {
display: flex;
align-items: center;
}
:deep(.el-pagination.is-background .el-pager li) {
min-width: 32px;
height: 32px;
line-height: 32px;
border-radius: 6px;
margin: 0 6px;
border: 1px solid rgba(0, 0, 0, 0.15);
background-color: #fff;
color: rgb(95, 101, 108);
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
}
:deep(.el-pagination.is-background .el-pager li.is-active) {
background-color: #fff;
color: rgba(22, 119, 255, 1);
border-color: rgba(22, 119, 255, 1);
}
:deep(.el-pagination.is-background .el-pager li.is-ellipsis) {
border: none;
background-color: transparent;
color: rgb(95, 101, 108);
min-width: 16px;
margin: 0 6px;
}
:deep(.el-pagination.is-background .btn-prev),
:deep(.el-pagination.is-background .btn-next) {
min-width: 32px;
height: 32px;
border-radius: 6px;
border: 1px solid rgba(0, 0, 0, 0.15);
background-color: #fff;
color: rgb(95, 101, 108);
font-size: 16px;
font-family: "Microsoft YaHei";
margin: 0 6px;
}
:deep(.el-pagination.is-background .btn-prev.is-disabled),
:deep(.el-pagination.is-background .btn-next.is-disabled) {
color: rgba(95, 101, 108, 0.45);
border-color: rgb(235, 238, 242);
background-color: #fff;
}
</style>
......@@ -2,31 +2,73 @@ import * as echarts from 'echarts';
const getMultiLineChart = (data) => {
// 提取标题和系列数据
// const { title, series } = data;
const title = data.title
const series = data.data
// 定义配色数组
const colorList = [
'rgba(5, 95, 194, 1)', // #055fc2
'rgba(19, 168, 168, 1)', // #13a8a8
'rgba(250, 140, 22, 1)', // #fa8c16
'rgba(114, 46, 209, 1)', // #722ed1
'rgba(115, 209, 61, 1)', // #73d13d
'rgba(206, 79, 81, 1)', // #ce4f51
'rgba(145, 202, 255, 1)', // #91caff
'rgba(95, 101, 108, 1)', // #5f656c
'rgba(250, 84, 28, 1)', // #fa541c
'rgba(47, 84, 235, 1)', // #2f54eb
'rgba(64, 150, 255, 1)', // #4096ff
'rgba(34, 41, 52, 1)', // #222934
'rgba(173, 198, 255, 1)', // #adc6ff
'rgba(255, 169, 64, 1)' // #ffa940
];
// 解析 RGBA 颜色的辅助函数
const parseRgba = (colorStr) => {
// 匹配 rgba(r, g, b, a) 格式
const match = colorStr.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(\.\d+)?)\)/);
if (match) {
return {
r: parseInt(match[1]),
g: parseInt(match[2]),
b: parseInt(match[3]),
a: parseFloat(match[4])
};
}
// 默认返回黑色
return { r: 0, g: 0, b: 0, a: 1 };
};
// 动态生成 series 配置
const echartsSeries = series.map((item, index) => ({
name: item.name,
type: 'line',
// areaStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: item.color || `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, 0.7)` // 随机颜色
// },
// {
// offset: 1,
// color: item.color ? `${item.color.replace('0.7', '0')}` : `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, 0)` // 随机颜色
// }
// ])
// },
emphasis: {
focus: 'series'
},
data: item.value
}));
const echartsSeries = series.map((item, index) => {
// 获取当前系列的颜色(优先使用item.color,否则用预设颜色,再否则随机)
const baseColor = item.color || colorList[index % colorList.length] || `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, 1)`;
const { r, g, b } = parseRgba(baseColor);
return ({
name: item.name,
type: 'line',
// 新增/优化:面积填充渐变效果
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0, // 顶部
color: `rgba(${r}, ${g}, ${b}, 0.3)` // 0.3 透明度
},
{
offset: 1, // 底部
color: `rgba(${r}, ${g}, ${b}, 0)` // 0 透明度
}
])
},
symbolSize: 8,
emphasis: {
focus: 'series'
},
data: item.value
});
});
return {
tooltip: {
......@@ -50,9 +92,16 @@ const getMultiLineChart = (data) => {
top: 10,
left: 'center',
icon: 'circle',
textStyle: {
fontFamily: 'Source Han Sans CN', // 字体
fontWeight: 400, // 字重值(Regular对应400)
fontSize: 14, // 字号
lineHeight: 24, // 行高
letterSpacing: 0, // 字间距
align: 'left' // 文本左对齐
}
},
// color: series.map(item => item.color || `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, 0.7)`), // 动态颜色
color: ['#055fc2', '#13a8a8', '#fa8c16', '#722ed1', '#73d13d', '#ce4f51', '#91caff', '#5f656c', '#fa541c', '#2f54eb', '#4096ff', '#222934', '#adc6ff', '#ffa940'], // 色彩调和的折线图配色方案
color: colorList, // 使用预设的配色数组
xAxis: [
{
type: 'category',
......@@ -62,7 +111,15 @@ const getMultiLineChart = (data) => {
],
yAxis: [
{
type: 'value'
type: 'value',
splitLine: {
show: true, // 显示网格线
lineStyle: {
color: 'rgba(231, 241, 255, 1)',
type: 'dashed',
width: 1
}
}
}
],
series: echartsSeries
......
......@@ -20,7 +20,13 @@ const getPieChart = (data) => {
},
label: {
alignTo: 'edge',
formatter: '{name|{b}}\n{time|{c} 条 {d}%}',
formatter: params => {
const name = params.name || "";
const value = params.value ?? "";
const percent = params.percent != null ? Math.round(params.percent) : 0;
return `{name|${name}}\n{time|${value}${percent}%}`;
},
minMargin: 5,
edgeDistance: 10,
lineHeight: 20,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论