提交 2a5ddbf3 authored 作者: 朱政's avatar 朱政

Merge branch 'pre' into zz-dev

流水线 #426 已通过 于阶段
in 1 分 31 秒
......@@ -2,42 +2,42 @@ import request from "@/api/request.js";
// 规则限制-首页统计接口
export function getStatCount() {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/statCount`
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/statCount`
});
}
// 规则限制-查询最新动态接口
export function getLatestUpdates() {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getLatestUpdates`
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getLatestUpdates`
});
}
// 规则限制-风险信号
export function getRiskSignal(params) {
return request({
method: 'GET',
url: `/api/commonFeature/riskSignal/${params}`
})
return request({
method: "GET",
url: `/api/commonFeature/riskSignal/${params}`
});
}
// 规则限制-查询新闻资讯
export function getNews(params) {
return request({
method: 'GET',
url: `/api/commonFeature/news/${params}`
})
return request({
method: "GET",
url: `/api/commonFeature/news/${params}`
});
}
// 规则限制-查询社交媒体
export function getRemarks(params) {
return request({
method: 'GET',
url: `/api/commonFeature/remarks/${params}`
})
return request({
method: "GET",
url: `/api/commonFeature/remarks/${params}`
});
}
// 规则限制-限制领域分布情况
......@@ -47,11 +47,11 @@ export function getRemarks(params) {
* @header token
*/
export function getAreaDistribution(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getAreaDistribution`,
params
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getAreaDistribution`,
params
});
}
// 规则限制-受限实体数量变化趋势
......@@ -62,11 +62,11 @@ export function getAreaDistribution(params) {
* @header token
*/
export function getEntityChangeTrend(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getEntityChangeTrend`,
params
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getEntityChangeTrend`,
params
});
}
// 规则限制-规则限制政令列表查询接口
......@@ -82,11 +82,11 @@ export function getEntityChangeTrend(params) {
* @header token
*/
export function getRuleLimitList(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getRuleLimitList`,
params
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getRuleLimitList`,
params
});
}
// 规则限制-排华科技联盟列表接口
......@@ -103,55 +103,52 @@ export function getRuleLimitList(params) {
* @header token
*/
export function getACTAList(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getACTAList`,
params
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getACTAList`,
params
});
}
export function getAcTAAllcountry() {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getACTAAllCountry/`
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getACTAAllCountry/`
});
}
// 规则限制-规则限制基本详情
export function getSanctionOverview(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getSanctionOverview/${params}`
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getSanctionOverview/${params}`
});
}
// 规则限制-背景分析
export function getBackGround(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getBackGround/${params}`
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getBackGround/${params}`
});
}
// 规则限制-限制条款
export function getLimitClause(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getLimitClause/${params}`
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getLimitClause/${params}`
});
}
// 规则限制-相关举措
export function getRelevantMeasures(params) {
return request({
method: 'GET',
url: `/api/ruleLimitInfo/getRelevantMeasures/${params}`
})
return request({
method: "GET",
url: `/api/ruleLimitInfo/getRelevantMeasures/${params}`
});
}
// // 实体清单-制裁概况-获取发布机构机构动态
// /**
// * @param {Object} data
......@@ -167,8 +164,26 @@ export function getRelevantMeasures(params) {
// }
export function getRuleOrg(params) {
return request({
method: 'POST',
url: `/api/organization/relate/ruleOrg`, data: params
})
}
\ No newline at end of file
return request({
method: "POST",
url: `/api/organization/relate/ruleOrg`,
data: params
});
}
// 排华联盟-联盟简介
export function getUnionIntroduction(unionId) {
return request({
method: "GET",
url: `/api/ruleLimitInfo/getUnionIntroduction/${unionId}`
});
}
// 排华联盟-联盟动态
export function getUnionDynamicList(params) {
return request({
method: "GET",
url: `/api/ruleLimitInfo/getUnionDynamicList/${params.unionId}`,
params: { currentPage: params.currentPage, pageSize: params.pageSize }
});
}
......@@ -499,7 +499,8 @@ onMounted(() => {
<style lang="scss" scoped>
.module-header-wrapper {
width: 100%;
// height: 64px;
position: relative;
z-index: 101;
border-bottom: 1px solid rgba(234, 236, 238, 1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: linear-gradient(180deg, rgba(246, 250, 255, 0.8) 0%, rgba(255, 255, 255, 0.8) 100%);
......
// 规则限制
const RuleRestriction = () => import('@/views/ruleRestriction/index.vue')
const RuleRestrictionDetail = () => import('@/views/ruleRestriction/detail/index.vue')
const RuleRestrictionsAlliance = () => import('@/views/ruleRestriction/alliance/index.vue')
const ruleRestrictionsRoutes = [
// 规则限制
{
path: "/ruleRestrictions",
name: "RuleRestrictions",
component: RuleRestriction,
meta: {
title: "规则限制概览",
isShowHeader: true
}
},
// 规则限制详情
{
path: "/ruleRestrictions/detail",
name: "RuleRestrictionsDetail",
component: RuleRestrictionDetail,
meta: {
title: "规则限制详情",
dynamicTitle: true
}
}, {
path: "/ruleRestrictions/alliance",
name: "RuleRestrictionsAlliance",
component: RuleRestrictionsAlliance,
meta: {
title: "规则限制联盟详情",
dynamicTitle: true
}
},
const RuleRestriction = () => import("@/views/ruleRestriction/index.vue");
const RuleRestrictionDetail = () => import("@/views/ruleRestriction/detail/index.vue");
const RuleRestrictionsAlliance = () => import("@/views/ruleRestriction/alliance/index.vue");
]
const ruleRestrictionsRoutes = [
// 规则限制
{
path: "/ruleRestrictions",
name: "RuleRestrictions",
component: RuleRestriction,
meta: {
title: "规则限制概览",
isShowHeader: true
}
},
// 规则限制详情
{
path: "/ruleRestrictions/detail",
name: "RuleRestrictionsDetail",
component: RuleRestrictionDetail,
meta: {
title: "规则限制详情",
dynamicTitle: true
}
},
{
path: "/ruleRestrictions/alliance",
name: "RuleRestrictionsAlliance",
component: RuleRestrictionsAlliance,
meta: {
title: "规则限制联盟详情",
isShowHeader: true,
dynamicTitle: true
}
}
];
export default ruleRestrictionsRoutes
export default ruleRestrictionsRoutes;
......@@ -54,41 +54,59 @@
}
/***tabs-bar左边悬浮***/
.left-float-nav-tabs,
.left-float-nav-tabs .el-tabs {
overflow: visible !important;
width: auto !important;
}
.left-float-nav-tabs {
position: relative;
.el-tabs__header.is-left {
position: absolute;
left: -140px;
top: 0px;
position: absolute !important;
left: -160px !important;
top: 0 !important;
width: auto !important;
display: flex;
flex-direction: column;
align-items: center;
overflow: visible !important;
.el-tabs__nav {
display: flex;
flex-direction: column;
gap: 16px;
align-items: center;
overflow: visible !important;
float: none !important;
}
.el-tabs__active-bar {
background-color: transparent;
right: 12px;
top: 11px;
height: 8px !important;
border-top: 6px solid transparent;
/* 顶部边框透明 */
border-bottom: 6px solid transparent;
/* 底部边框透明 */
border-left: 8px solid var(--bg-white-100);
/* 左侧边框有颜色 */
display: none;
}
}
.el-tabs__content {
display: none;
}
.el-tabs__item.is-left {
@extend .text-tip-1;
color: var(--text-primary-65-color);
height: 32px;
padding: 4px 26px 4px 28px;
border-radius: 16px 16px 16px 16px;
padding: 4px 16px;
border-radius: 16px;
justify-content: center;
color: var(--text-primary-65-color);
background-color: var(--bg-white-100);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
border: none !important;
width: auto;
}
.el-tabs__item.is-left.is-active {
color: var(--bg-white-100);
background-color: var(--color-primary-100);
color: var(--bg-white-100) !important;
background-color: var(--color-primary-100) !important;
box-shadow: none;
}
}
\ No newline at end of file
......@@ -270,6 +270,8 @@ $axis-width: 2px;
.axis-col {
width: $node-size;
flex-shrink: 0;
position: relative;
// 修复:轴线不穿刺圆点 - 改为 flex-start,圆点用负margin浮在边界上
display: flex;
flex-direction: column;
align-items: center;
......@@ -281,7 +283,10 @@ $axis-width: 2px;
min-height: 12px;
&.invisible {
background-color: transparent;
// 第一个节点上方无线:隐藏并占位,使圆点紧贴timeline起点
height: 0;
min-height: 0;
overflow: hidden;
}
}
......@@ -290,12 +295,28 @@ $axis-width: 2px;
height: $node-size;
border-radius: 50%;
flex-shrink: 0;
overflow: hidden;
overflow: visible; // 改为 visible,使负 margin 不被裁剪
position: relative;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
// 第一个节点特殊处理:居顶,上方无线
&:first-child {
margin-top: 0;
}
// 后续节点使用负 margin 浮在轴线上
&:not(:first-child) {
margin-top: -$node-size / 2;
}
// 最后一个节点特殊处理:下方无线
&:last-child {
margin-bottom: 0;
}
// 非首尾节点使用负 margin
&:not(:first-child):not(:last-child) {
margin-bottom: -$node-size / 2;
}
&.highlight {
background-color: rgba(245, 34, 45, 1);
......
......@@ -23,7 +23,10 @@
</div>
<!-- ECharts word cloud -->
<div ref="chartRef" class="pna-cloud"></div>
<div v-if="keywords.length > 0" ref="chartRef" class="pna-cloud"></div>
<div v-else class="pna-cloud">
<el-empty description="暂无数据" :image-size="80" />
</div>
</div>
</template>
......@@ -172,5 +175,8 @@ onBeforeUnmount(() => {
.pna-cloud {
flex: 1;
min-height: 400px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
......@@ -32,11 +32,12 @@
</div>
</div>
<div class="pn-rows" :class="{ 'pn-rows-loading': loading }">
<div class="pn-rows" :class="{ 'pn-rows-loading': loading || newsList.length === 0 }">
<div v-if="loading" class="pn-rows-spinner">
<div class="pn-spinner-icon"></div>
<span class="pn-spinner-text">加载中...</span>
</div>
<el-empty v-else-if="newsList.length === 0" description="暂无数据" :image-size="80" />
<div
v-for="(item, index) in newsList"
v-show="!loading"
......@@ -52,7 +53,7 @@
</div>
</div>
<div class="pn-footer">
<div class="pn-footer" v-if="newsList.length > 0">
<span class="pn-footer-total">{{ total }}条关键新闻</span>
<div class="pn-pagination">
<button
......
......@@ -95,7 +95,11 @@
</div>
</template>
<div class="main">
<div v-for="item in CharacterLatestDynamic" :key="item" class="main-item">
<template v-if="CharacterLatestDynamic.length === 0">
<el-empty description="暂无数据" :image-size="80" />
</template>
<template v-else>
<div v-for="item in CharacterLatestDynamic" :key="item" class="main-item">
<div class="time">
<div class="year">{{ item.time.split("-")[0] }}</div>
<div class="date">{{ item.time.split("-")[1] + "月" + item.time.split("-")[2] + "日" }}
......@@ -127,9 +131,9 @@
</div>
</div>
</div>
<!-- <div class="line-test"></div> -->
</template>
</div>
<div class="pagination">
<div v-if="CharacterLatestDynamic.length > 0" class="pagination">
<div class="total">{{ `共 ${total} 项` }}</div>
<el-pagination @current-change="handleCurrentChange" :page-size="pageSize"
:current-page="currentPage" background layout="prev, pager, next" :total="total"
......@@ -233,29 +237,25 @@
</div>
</div>
<!-- 历史提案 -->
<!-- 在 member-of-congress 同级的左侧添加标签栏 -->
<!-- 历史提案 tab 对应的内容区 -->
<div v-if="infoActive === '历史提案'" class="proposal-wrapper">
<div v-if="infoActive === '历史提案'" class="proposal-wrapper">
<div class="proposal-tab-switcher">
<button :class="['proposal-tab', { active: newsTab === 'history' }]" @click="newsTab = 'history'">
<span>历史提案</span>
<svg v-if="newsTab === 'history'" class="proposal-tab-arrow" width="12" height="12"
viewBox="0 0 12 12" fill="currentColor">
<path d="M4 2l5 4-5 4V2z" />
<svg v-if="newsTab === 'history'" class="proposal-tab-arrow" width="8" height="8" viewBox="0 0 8 8" fill="currentColor">
<path d="M4 0L8 4L4 8V0Z" />
</svg>
</button>
<button :class="['proposal-tab', { active: newsTab === 'potential' }]" @click="newsTab = 'potential'">
<span>潜在提案</span>
<svg v-if="newsTab === 'potential'" class="proposal-tab-arrow" width="12" height="12"
viewBox="0 0 12 12" fill="currentColor">
<path d="M4 2l5 4-5 4V2z" />
<svg v-if="newsTab === 'potential'" class="proposal-tab-arrow" width="8" height="8" viewBox="0 0 8 8" fill="currentColor">
<path d="M4 0L8 4L4 8V0Z" />
</svg>
</button>
</div>
<HistoricalProposal v-if="newsTab === 'history'" />
<PotentialNews v-else />
</div>
</div>
<CharacterRelationships v-if="infoActive === '人物关系'" />
<RelevantSituation v-if="infoActive === '相关情况'" />
<!-- 弹框 -->
......@@ -1837,45 +1837,40 @@ const handleClickTag = async (tag) => {
/* 作为定位参考 */
}
.proposal-tab.active {
background: #055FC2;
color: #fff;
}
.proposal-tab-switcher {
position: absolute;
right: calc(100% + 24px);
left: 24px;
top: 0;
display: flex;
flex-direction: column;
gap: 12px;
z-index: 1;
gap: 16px;
align-items: center;
}
.proposal-tab {
width: 120px;
width: 112px;
height: 32px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 12px;
font-family: 'Source Han Sans CN', 'Noto Sans SC', sans-serif;
justify-content: center;
gap: 4px;
padding: 0 16px;
border-radius: 16px;
border: none;
font-size: 16px;
font-family: 'Microsoft YaHei', sans-serif;
font-weight: 400;
color: #8c8c8c;
background: none;
border: none;
border-radius: 20px;
color: var(--text-primary-65-color);
background-color: var(--bg-white-100);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
cursor: pointer;
white-space: nowrap;
box-sizing: border-box;
}
.proposal-tab.active {
background: #055FC2;
color: #fff;
&.active {
color: var(--bg-white-100);
background-color: var(--color-primary-100);
box-shadow: none;
}
}
.proposal-tab-arrow {
......
/**
* 人物主页 - 类型配置
* type 1: 科技领袖, type 2: 国会议员, type 3: 智库研究人员
*/
export const CHARACTER_CONFIG = {
1: {
// 科技领袖
rootClass: "tech-leader",
tabs: ["人物详情", "人物关系"],
tabWidth: "50%",
useImageProxy: false,
headerTagType: "areaTag",
wordCloudTitle: "科技观点",
yearDefault: "全部时间",
yearBuildMode: "dynamic",
yearStaticOptions: [],
showFundSource: false,
resumeMode: "inline",
resumeTitle: "职业履历",
resumeHeight: "1336px",
companySectionTitle: "实体信息",
basicInfoFields: [
{ label: "出生日期:", key: "birthday", type: "text" },
{ label: "国籍:", key: "country", type: "text" },
{ label: "教育背景:", key: "educationList", type: "education", format: "school(major)" },
{ label: "净资产:", key: "assets", type: "text" },
{ label: "职业:", key: "positionTitle", type: "text" },
{ label: "婚姻状况:", key: "marital", type: "text" },
{ label: "出生地:", key: "birthPlace", type: "text" }
],
boxHeightRules: [
{ condition: "undefined", value: "605px" },
{ condition: "empty", value: "405px" },
{ condition: "lte2", value: "505px" },
{ condition: "default", value: "625px" }
],
useAreaTypeApi: true,
fieldViewMode: "areaList",
dialogTagPrefix: "#",
dialogTagSuffix: " 相关领域标签",
showRelevantSituation: false,
historicalProposalType: null
},
2: {
// 国会议员
rootClass: "member-of-congress",
tabs: ["人物详情", "历史提案", "人物关系"],
tabWidth: "auto",
useImageProxy: true,
headerTagType: "inline",
wordCloudTitle: "科技观点",
yearDefault: "全部",
yearBuildMode: "static",
yearStaticOptions: ["全部", "2025", "2024", "2023", "2022", "2021", "2020"],
showFundSource: true,
resumeMode: "inline",
resumeTitle: "职业履历",
resumeHeight: "1556px",
companySectionTitle: "社交媒体",
basicInfoFields: [
{ label: "出生日期:", key: "birthday", type: "text" },
{ label: "现任职位:", key: "positionTitle", type: "text" },
{ label: "党派归属:", key: "party", type: "text" },
{ label: "教育背景:", key: "educationList", type: "education", format: "school+major" },
{ label: "代表州/选区:", key: "state", type: "text", titleClass: "address" },
{ label: "政治立场:", key: "political", type: "text", contentClass: "long" },
{ label: "出生地:", key: "birthPlace", type: "text" }
],
boxHeightRules: [
{ condition: "undefined", value: "545px" },
{ condition: "empty", value: "495px" },
{ condition: "lte2", value: "445px" },
{ condition: "default", value: "545px" }
],
useAreaTypeApi: false,
fieldViewMode: "sessionStorage",
dialogTagPrefix: "#",
dialogTagSuffix: "相关领域标签",
showRelevantSituation: false,
historicalProposalType: "bill"
},
3: {
// 智库研究人员
rootClass: "think-tank-person",
tabs: ["人物详情", "成果报告", "人物关系"],
tabWidth: "auto",
useImageProxy: false,
headerTagType: "areaTag",
wordCloudTitle: "核心观点",
yearDefault: "全部",
yearBuildMode: "static",
yearStaticOptions: ["全部", "2026", "2025", "2024", "2023", "2022", "2021"],
showFundSource: false,
resumeMode: "card",
resumeTitle: "政治履历",
resumeHeight: null,
companySectionTitle: "社交媒体",
basicInfoFields: [
{ label: "出生日期:", key: "birthday", type: "text" },
{ label: "现任职位:", key: "positionTitle", type: "text" },
{ label: "兼任职位:", key: "sideJob", type: "text" },
{ label: "政策倾向:", key: "political", type: "text" },
{ label: "国籍:", key: "country", type: "text" },
{ label: "教育背景:", key: "educationList", type: "education", format: "school(major)" },
{ label: "研究领域:", key: "industryList", type: "industry" }
],
boxHeightRules: [
{ condition: "undefined", value: "625px" },
{ condition: "empty", value: "425px" },
{ condition: "lte2", value: "525px" },
{ condition: "default", value: "625px" }
],
useAreaTypeApi: false,
fieldViewMode: "sessionStorage",
dialogTagPrefix: "",
dialogTagSuffix: "",
showRelevantSituation: false,
historicalProposalType: "news"
}
};
<template>
<div class="character-page">
<img src="./assets/images/background.png" alt="" class="bg" />
<!-- 主要内容 -->
<ModuleHeader />
<!-- 主要内容 -->
<div class="main">
<!-- 科技领袖 -->
<tech-leader v-if="type == 1"/>
<!-- 国会议员 -->
<member-of-congress v-if="type == 2" />
<!-- 智库研究人员 -->
<think-tank-person v-if="type == 3" />
<unified-character :type="type" :person-id="personId" />
</div>
</div>
</template>
......@@ -16,9 +12,8 @@
<script setup>
import { ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import TechLeader from './components/techLeader/index.vue';
import MemberOfCongress from './components/memberOfCongress/index.vue';
import ThinkTankPerson from './components/thinkTankPerson/index.vue';
import UnifiedCharacter from './components/unified/index.vue';
import ModuleHeader from '@/components/base/moduleHeader/index.vue';
import { getCharacterGlobalInfo } from "@/api/characterPage/characterPage.js";
......@@ -57,7 +52,7 @@ const getCharacterGlobalInfoFn = async () => {
}catch(error){
}
};
onMounted(() => {
......
......@@ -21,28 +21,31 @@
<div class="flex-display content-row">
<div class="left-col">
<AnalysisBox title="打压动态" :showAllBtn="false">
<AnalysisBox title="动态" :showAllBtn="false">
<div class="news-list-wrap">
<div class="news-scroll-area">
<div
v-for="item in newsList"
:key="item.id"
class="news-item flex-display mouse-hover"
@click="handleNewsClick(item)"
>
<div class="item-thumb flex-display-center">
<span class="item-thumb-text">新闻资讯</span>
</div>
<div class="item-body">
<p class="text-tip-1-bold text-primary-80-clor item-title">{{ item.title }}</p>
<p class="text-tip-2 text-primary-65-clor item-content">{{ item.content }}</p>
</div>
<div class="item-meta flex-display">
<span class="text-tip-2 text-primary-50-clor">{{ item.date }}</span>
<span class="text-tip-2 text-primary-50-clor meta-sep">·</span>
<span class="text-tip-2 text-primary-50-clor">{{ item.source }}</span>
<template v-for="(item, idx) in newsList" :key="item.id">
<div
class="news-item flex-display mouse-hover"
@click="handleNewsClick(item)"
>
<div class="item-thumb flex-display-center">
<span class="item-thumb-text">新闻资讯</span>
</div>
<div class="item-body">
<div class="item-top flex-display">
<p class="text-tip-1-bold text-primary-80-clor item-title">{{ item.title }}</p>
<div class="item-meta flex-display">
<span class="text-tip-2 text-primary-65-clor">{{ item.date }}</span>
<span class="text-tip-2 text-primary-65-clor meta-sep">·</span>
<span class="text-tip-2 text-primary-65-clor">{{ item.source }}</span>
</div>
</div>
<p class="text-tip-2 text-primary-65-clor item-content">{{ item.content }}</p>
</div>
</div>
</div>
<div v-if="idx < newsList.length - 1" class="news-divider"></div>
</template>
</div>
<div class="pagination-row flex-display">
......@@ -59,7 +62,7 @@
@click="changePage(p)"
>{{ p }}</button>
<span v-if="pagination.page < pagination.totalPages - 2" class="page-ellipsis text-primary-50-clor">...</span>
<button class="page-btn" :class="{ active: pagination.page === pagination.totalPages }" @click="changePage(pagination.totalPages)">{{ pagination.totalPages }}</button>
<button v-if="pagination.totalPages > 1" class="page-btn" :class="{ active: pagination.page === pagination.totalPages }" @click="changePage(pagination.totalPages)">{{ pagination.totalPages }}</button>
<button class="page-btn" :disabled="pagination.page === pagination.totalPages" @click="changePage(pagination.page + 1)">&gt;</button>
</div>
</div>
......@@ -68,7 +71,7 @@
</div>
<div class="right-col">
<AnalysisBox title="联盟简介" :showAllBtn="false">
<AnalysisBox title="简介" :showAllBtn="false">
<div class="intro-wrap">
<div class="intro-row flex-display">
<span class="text-tip-2-bold text-primary-80-clor intro-label">时间:</span>
......@@ -104,7 +107,7 @@ import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import AnalysisBox from '@/components/base/boxBackground/analysisBox.vue'
import AreaTag from '@/components/base/AreaTag/index.vue'
import { getNewsDetail, getNewsList } from './mock/newsDetail'
import { getUnionIntroduction, getUnionDynamicList } from '@/api/ruleRestriction/index.js'
const route = useRoute()
const router = useRouter()
......@@ -125,10 +128,10 @@ const newsDetail = ref({
const newsList = ref([])
const pagination = ref({
page: 5,
page: 1,
pageSize: 10,
total: 153,
totalPages: 16
total: 0,
totalPages: 1
})
const visiblePages = computed(() => {
......@@ -145,16 +148,48 @@ const visiblePages = computed(() => {
return pages
})
const loadNewsDetail = () => {
newsDetail.value = getNewsDetail(newsId.value)
const loadNewsDetail = async () => {
try {
const res = await getUnionIntroduction(newsId.value)
if (res.code === 200) {
const data = res.data
newsDetail.value = {
title: data.unionNameZh || '',
subTitle: data.unionName || '',
tags: data.domains || [],
time: data.time || '',
background: data.background || '',
countries: (data.memberCountries || []).map(c => ({ name: c.countryName }))
}
}
} catch (error) {
console.error('获取联盟简介失败:', error)
}
}
const loadNewsList = (page = 1) => {
const data = getNewsList(page, pagination.value.pageSize)
newsList.value = data.list
pagination.value.page = data.page
pagination.value.total = data.total
pagination.value.totalPages = data.totalPages
const loadNewsList = async (page = 1) => {
try {
const res = await getUnionDynamicList({
unionId: newsId.value,
currentPage: page,
pageSize: pagination.value.pageSize
})
if (res.code === 200) {
const data = res.data
newsList.value = (data.content || []).map(item => ({
id: item.newsId,
title: item.title || '',
content: item.summary || '',
date: item.publishedTime || '',
source: item.source || ''
}))
pagination.value.page = page
pagination.value.total = data.totalElements || 0
pagination.value.totalPages = data.totalPages || 1
}
} catch (error) {
console.error('获取联盟动态失败:', error)
}
}
const changePage = (page) => {
......@@ -168,11 +203,14 @@ const handleNewsClick = (item) => {
onMounted(() => {
loadNewsDetail()
loadNewsList(pagination.value.page)
loadNewsList(1)
})
</script>
<style lang="scss" scoped>
:deep(.main-container1){
overflow: auto;
}
.page-wrap {
width: 100%;
min-height: 100vh;
......@@ -228,7 +266,6 @@ onMounted(() => {
.left-col {
width: 1064px;
height: 1284px;
flex-shrink: 0;
}
......@@ -241,33 +278,32 @@ onMounted(() => {
.news-list-wrap {
display: flex;
flex-direction: column;
height: calc(100% - 48px);
padding: 0 20px;
}
.news-scroll-area {
flex: 1;
min-height: 0;
overflow-y: auto;
}
.news-item {
gap: 16px;
padding: 16px 0;
border-bottom: 1px solid #eaecee;
align-items: flex-start;
gap: 20px;
padding: 0;
align-items: center;
cursor: pointer;
transition: background 0.15s;
}
&:last-child {
border-bottom: none;
}
.news-divider {
width: 100%;
height: 1px;
background: #f0f2f4;
margin: 12px 0;
}
.item-thumb {
width: 100px;
height: 70px;
border-radius: 6px;
width: 97px;
height: 72px;
border-radius: 4px;
background: linear-gradient(135deg, #4a7bf7 0%, #6b8cff 100%);
flex-shrink: 0;
}
......@@ -280,13 +316,24 @@ onMounted(() => {
.item-body {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 4px;
}
.item-top {
align-items: center;
width: 100%;
gap: 0;
}
.item-title {
margin: 0 0 6px 0;
margin: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex: 1;
min-width: 0;
}
.item-content {
......
......@@ -224,6 +224,19 @@ export default {
:deep(.el-timeline) {
max-width: 688px !important;
padding: 0;
overflow: hidden;
}
:deep(.el-timeline-item) {
padding-bottom: 4px;
}
:deep(.el-timeline-item:last-child) {
padding-bottom: 0;
}
:deep(.el-timeline-item:last-child .el-timeline-item__wrapper) {
padding-bottom: 0;
}
:deep(.el-timeline-item__wrapper) {
......@@ -253,4 +266,9 @@ export default {
text-align: justify;
}
:deep(.el-timeline-item:last-child .el-timeline-item__tail) {
visibility: hidden;
display: none;
}
</style>
......@@ -28,9 +28,9 @@
<!-- 涉华观点次数列 -->
<div class="row-col col-count">
<el-progress :percentage="getProgress(item.mediaQuoteCount)" :show-text="false"
style="/* 矩形 244 */ width: 82px; height: 8px" :status="getStatus(getProgress(item.mediaQuoteCount))" />
<span class="count-text">{{ item.mediaQuoteCount }}</span>
<el-progress :percentage="getProgress(item.chinaRelatedCount)" :show-text="false"
style="/* 矩形 244 */ width: 82px; height: 8px" :status="getStatus(getProgress(item.chinaRelatedCount))" />
<span class="count-text">{{ item.chinaRelatedCount }}</span>
</div>
<!-- 媒体引用次数列 -->
......@@ -46,7 +46,6 @@
</template>
<script setup>
import { ref,onMounted,defineProps,watch } from "vue";
import personData from "../json/personData.json"; // 引入JSON数据
import {getMainCharactersView } from "@/api/technologyFigures/technologyFigures";
import { useCharacterNav } from "../utils/useCharacterNav";
const { handleClickToCharacter } = useCharacterNav();
......@@ -99,14 +98,16 @@ const handlegetMainCharactersViewFn = async () => {
});
}
} catch (error) {}
} catch (error) {
console.error("获取主要人物涉华观点统计失败:", error);
}
};
onMounted(async () => {
handlegetMainCharactersViewFn();
});
const personList = ref();
const personList = ref([]);
// 进度条状态
const getStatus = _percent => {
const percent = _percent;
......@@ -120,8 +121,9 @@ const getStatus = _percent => {
};
// 计算进度条宽度(基于最大值的百分比)
const getMaxCount = () => {
const counts = personList.value.flatMap(item => [item.chinaRelatedCount, item.mediaQuoteCount]);
return Math.max(...counts);
const counts = personList.value.flatMap(item => [item.chinaRelatedCount || 0, item.mediaQuoteCount || 0]);
if (counts.length === 0) return 1;
return Math.max(...counts, 1);
};
const getProgress = count => (count / getMaxCount()) * 100;
</script>
......
......@@ -12,7 +12,7 @@
<img :src="item.avatar" alt="" class="source-library-avatar" />
</div>
<div class="source-library-text-content">
<div class="card-main" :class="{ 'no-title': !item.title }">
<div class="card-main" ">
<h3 class="source-library-name">{{ item.name }}</h3>
<p class="source-library-title" v-if="item.title">{{ item.title }}</p>
<div class="taglist">
......@@ -177,7 +177,11 @@ const handleClcikToCharacter = async id => {
ElMessage.warning("找不到当前人员的类型值!");
return;
}
} catch (error) {}
} catch (error) {
if (error.name !== "AbortError") {
console.error("获取人物资源库失败:", error);
}
}
};
onMounted(async () => {
......@@ -209,7 +213,7 @@ const handlePageChange = p => {
box-sizing: border-box;
display: flex;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: var(---10, 10px);
border-radius: 10px;
padding: 20px 18px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
......@@ -249,9 +253,9 @@ const handlePageChange = p => {
.source-library-avatar {
/* 椭圆 142 */
width: 88px;
height: 88px;
border-radius: 50%;
width: 92px;
height: 121px;
// border-radius: 50%;
}
.source-library-text-content {
......
......@@ -81,11 +81,6 @@
import * as echarts from "echarts";
import worldJson from "@/assets/json/world.json";
import { getCharacterTrends } from "@/api/technologyFigures/technologyFigures";
import { ref } from "vue";
const CharacterTrends = ref([]);
const time = ref("");
const date = ref("");
const handlegetCharacterTrendsFn = async () => {
const params = {
......@@ -104,7 +99,9 @@ const handlegetCharacterTrendsFn = async () => {
};
});
}
} catch (error) {}
} catch (error) {
console.error("获取人物动向失败:", error);
}
};
function getDateDaysAgo(days) {
......@@ -169,6 +166,9 @@ export default {
tickWidth: 10,
viewStartIndex: 0,
viewDays: 120,
CharacterTrends: [],
time: "",
date: "",
};
},
computed: {
......
......@@ -12,7 +12,7 @@
<p class="speech-stance-title">{{ item.positionTitle }}</p>
</div>
<p class="speech-stance-content" :title="item.remarks">{{ item.remarks }}</p>
<p class="speech-stance-content" :title="item.remarks"><span class="speech-stance-text">{{ item.remarks }}</span></p>
</div>
</div>
......@@ -95,11 +95,11 @@ const handleClcikToCharacter = async id => {
const aId = ref();
const params = ref({});
watch(() => props.fieldSelected, (val) => {
aId.value = props.areaId;
if(val !== "全部领域"){
params.value.industryId = aId.value;
watch(() => [props.fieldSelected, props.areaId], (val) => {
const [fieldVal, areaVal] = val;
aId.value = areaVal;
if(fieldVal !== "全部领域"){
params.value.industryId = areaVal;
}else{
params.value = {};
}
......@@ -117,7 +117,9 @@ const handlegetPersonRelationFn = async () => {
if (res.code === 200) {
PersonRelation.value = res.data;
}
} catch (error) {}
} catch (error) {
console.error("获取重要人物言论及立场失败:", error);
}
};
onMounted(async () => {
......@@ -129,15 +131,13 @@ onMounted(async () => {
<style scoped>
.speech-stance-container {
width: 1530px;
/* max-width: 900px; */
margin: 0 auto;
margin: 5px 35px;
margin: 15px 35px;
}
.speech-stance-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 30px 9px;
gap: 28px 9px;
}
/* 响应式:小屏变一列 */
......@@ -204,8 +204,16 @@ onMounted(async () => {
line-height: 30px;
letter-spacing: 0px;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
/* 宽度保持不变,ellipsis 移至内部 span */
}
.speech-stance-text {
display: inline-block;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 24px;
vertical-align: top;
}
</style>
\ No newline at end of file
import * as echarts from "echarts";
const getMultiLineChart = (dataX, dataY1, dataY2, dataY3, dataY4, dataY5, dataY6) => {
return {
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#6a7985"
}
}
},
grid: {
top: "50px",
right: "50px",
bottom: "0px",
left: "40px",
containLabel: true
},
legend: {
data: ["人工智能", "集成电路", "量子科技", "生物科技", "通信网络", "能源"],
show: true,
top: "0px",
left: "center",
textStyle: {
color: "rgba(95, 101, 108, 1)",
fontFamily: "Microsoft YaHei",
fontSize: "16px"
}, // 设置图例标记为圆形
icon: "circle",
itemWidth: 10, // 圆的直径
itemHeight: 10, // 圆的直径
itemGap: 20 // 图例项之间的间距
},
color: [
"rgba(10, 87, 166, 1)", // 人工智能(深蓝色)
"rgba(64, 196, 181, 1)", // 集成电路(青绿色)
"rgba(114, 46, 209, 1)", // 量子科技(紫色)
"rgba(245, 141, 46, 1)", // 生物科技(橙色)
"rgba(111, 180, 255, 1)", // 通信网络(浅蓝色)
"rgba(196, 92, 68, 1)" // 能源(红褐色)
],
xAxis: [
{
type: "category",
boundaryGap: false,
data: dataX,
axisLabel: {
fontSize: 14 // 设置X轴字体大小
}
}
],
yAxis: [
{
type: "value",
splitLine: {
show: true,
lineStyle: {
type: "dashed",
color: "#E7F3FF"
}
},
axisLabel: {
fontSize: 14 // 设置X轴字体大小
},
}
],
series: [
{
name: "人工智能",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(10, 87, 166, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(10, 87, 166, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY1
},
{
name: "集成电路",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(64, 196, 181, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(64, 196, 181, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY2
},
{
name: "量子科技",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(114, 46, 209, 1)" // 起始颜色
},
{
offset: 1,
color: "rgba(114, 46, 209, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY3
},
{
name: "生物科技",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(245, 141, 46, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(245, 141, 46, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY4
},
{
name: "通信网络",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(111, 180, 255, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(111, 180, 255, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY5
},
{
name: "能源",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(196, 92, 68, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(196, 92, 68, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY6
}
]
};
return {
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#6a7985"
}
}
},
grid: {
top: "50px",
right: "24px",
bottom: "0px",
left: "24px",
containLabel: true
},
legend: {
data: ["人工智能", "集成电路", "量子科技", "生物科技", "通信网络", "能源"],
show: true,
top: "0px",
left: "center",
textStyle: {
color: "rgba(95, 101, 108, 1)",
fontFamily: "Microsoft YaHei",
fontSize: "16px"
}, // 设置图例标记为圆形
icon: "circle",
itemWidth: 10, // 圆的直径
itemHeight: 10, // 圆的直径
itemGap: 20 // 图例项之间的间距
},
color: [
"rgba(10, 87, 166, 1)", // 人工智能(深蓝色)
"rgba(64, 196, 181, 1)", // 集成电路(青绿色)
"rgba(114, 46, 209, 1)", // 量子科技(紫色)
"rgba(245, 141, 46, 1)", // 生物科技(橙色)
"rgba(111, 180, 255, 1)", // 通信网络(浅蓝色)
"rgba(196, 92, 68, 1)" // 能源(红褐色)
],
xAxis: [
{
type: "category",
boundaryGap: false,
data: dataX,
axisLabel: {
fontSize: 14,
color: "rgba(59, 65, 75, 1)"
},
axisLine: {
lineStyle: {
color: "#E7F3FF"
}
}
}
],
yAxis: [
{
type: "value",
splitLine: {
show: true,
lineStyle: {
type: "dashed",
color: "#E7F3FF"
}
},
axisLabel: {
fontSize: 14 // 设置X轴字体大小
}
}
],
series: [
{
name: "人工智能",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(10, 87, 166, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(10, 87, 166, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY1
},
{
name: "集成电路",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(64, 196, 181, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(64, 196, 181, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY2
},
{
name: "量子科技",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(114, 46, 209, 1)" // 起始颜色
},
{
offset: 1,
color: "rgba(114, 46, 209, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY3
},
{
name: "生物科技",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(245, 141, 46, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(245, 141, 46, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY4
},
{
name: "通信网络",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(111, 180, 255, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(111, 180, 255, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY5
},
{
name: "能源",
type: "line",
lineStyle: {
width: 1.5 // 单位:px,数值越大线条越粗
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(196, 92, 68, 0.2)" // 起始颜色
},
{
offset: 1,
color: "rgba(196, 92, 68, 0)" // 结束颜色
}
])
},
emphasis: {
focus: "series"
},
data: dataY6
}
]
};
};
export default getMultiLineChart;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论