提交 f6e09eda authored 作者: 朱政's avatar 朱政

feat:智库合作限制风险信号样式问题修改

上级 f58ff710
流水线 #590 已通过 于阶段
in 1 分 40 秒
<template>
<el-dialog
v-model="visible"
class="risk-signal-detail-dialog"
modal-class="risk-signal-detail-modal"
width="1280px"
align-center
:z-index="zIndex"
:show-close="true"
destroy-on-close
@closed="handleClosed"
>
<el-dialog v-model="visible" class="risk-signal-detail-dialog" modal-class="risk-signal-detail-modal" width="1280px"
align-center :z-index="zIndex" :show-close="true" destroy-on-close @closed="handleClosed">
<template #header>
<img class="header-icon" src="@/views/viewRiskSignal/assets/images/risk-icon.png" alt="" />
<span
v-if="listLevelText"
class="risk-signal-detail-dialog__level"
:class="listLevelModifierClass"
>{{ listLevelText }}</span>
<img class="header-icon" :src="headerIconSrc" alt="" />
<span v-if="listLevelText" class="risk-signal-detail-dialog__level" :class="listLevelModifierClass">{{
listLevelText }}</span>
<div v-if="bodyFromApi" class="risk-signal-detail-dialog__read-indicator">
<el-icon v-if="riskDetailStatus === false" class="risk-signal-detail-dialog__header-badge-close">
<Close />
</el-icon>
<img
v-else-if="riskDetailStatus === true"
class="risk-signal-detail-dialog__header-badge-read"
:src="greenRightImg"
alt=""
/>
<img v-else-if="riskDetailStatus === true" class="risk-signal-detail-dialog__header-badge-read"
:src="greenRightImg" alt="" />
<span v-if="riskDetailStatus != null" class="read">{{ riskDetailStatus ? "已读" : "未读" }}</span>
</div>
</template>
......@@ -35,28 +19,19 @@
<div v-if="riskDetailItem.title" class="risk-signal-detail-dialog__body">
<span class="risk-signal-detail-dialog__title">{{ riskDetailItem.title }}</span>
<div v-if="riskDetailItem.directionLabels.length" class="risk-signal-detail-dialog__directions">
<div
v-for="(dirLabel, dirIndex) in riskDetailItem.directionLabels"
<div v-for="(dirLabel, dirIndex) in riskDetailItem.directionLabels"
:key="'overview-risk-detail-direction-' + dirIndex + '-' + dirLabel"
class="risk-signal-detail-dialog__origin"
>{{ dirLabel }}</div>
class="risk-signal-detail-dialog__origin">{{ dirLabel }}</div>
</div>
<div class="risk-signal-detail-dialog__meta">
<span>{{ metaLine }}</span>
<div v-if="riskDetailItem.tag.length" class="risk-signal-detail-dialog__tags">
<AreaTag
v-for="(tag, index) in riskDetailItem.tag"
:key="'overview-risk-detail-tag-' + index + '-' + tag"
:tag-name="tag"
>{{ tag }}</AreaTag>
<AreaTag v-for="(tag, index) in riskDetailItem.tag" :key="'overview-risk-detail-tag-' + index + '-' + tag"
:tag-name="tag">{{ tag }}</AreaTag>
</div>
</div>
</div>
<div
v-if="showRelationBar"
class="risk-signal-detail-dialog_relation"
@click="handleRelationClick"
>
<div v-if="showRelationBar" class="risk-signal-detail-dialog_relation" @click="handleRelationClick">
<div class="relation">
<div class="logo">
<img src="@/views/viewRiskSignal/assets/images/logo.png" alt="" />
......@@ -72,12 +47,8 @@
</div>
</div>
<template #footer>
<el-button
type="primary"
class="risk-signal-detail-dialog__action-btn"
:loading="confirmLoading"
@click="handleConfirm"
>
<el-button type="primary" class="risk-signal-detail-dialog__action-btn" :loading="confirmLoading"
@click="handleConfirm">
确定
</el-button>
</template>
......@@ -91,6 +62,11 @@ import AreaTag from "@/components/base/AreaTag/index.vue";
import { ElMessage } from "element-plus";
import { Close } from "@element-plus/icons-vue";
import greenRightImg from "@/views/viewRiskSignal/assets/images/green-right.png";
import riskIconRed from "@/views/viewRiskSignal/assets/images/risk-icon-red.png";
import riskIconOrange from "@/views/viewRiskSignal/assets/images/risk-icon-orange.png";
import riskIconYellow from "@/views/viewRiskSignal/assets/images/risk-icon-yellow.png";
import riskIconGreen from "@/views/viewRiskSignal/assets/images/risk-icon-green.png";
import riskIconBlue from "@/views/viewRiskSignal/assets/images/risk-icon-blue.png";
import { getRiskSignalInfoById, updateRiskSignalStatus } from "@/api/riskSignal/index.js";
import {
buildListRowFallbackFromRawRow,
......@@ -180,6 +156,15 @@ const listLevelModifierClass = computed(
() => `risk-signal-detail-dialog__level--${getRiskDetailLevelModifier(listLevelText.value)}`
);
const headerIconSrc = computed(() => {
const lv = getRiskDetailLevelModifier(listLevelText.value);
if (lv === "lv1") return riskIconRed;
if (lv === "lv2") return riskIconOrange;
if (lv === "lv3") return riskIconYellow;
if (lv === "lv4") return riskIconGreen;
return riskIconBlue;
});
const fieldMap = computed(() => ({
nameField: props.nameField,
postDateField: props.postDateField,
......
......@@ -24,25 +24,29 @@ const props = defineProps({
margin: 0;
padding: 0;
}
.com-title {
width: 1575px;
width: 1600px;
height: 42px;
display: flex;
align-items: center;
.cl1 {
width: 24px;
height: 30px;
background-color: rgba(174, 214, 255, 1);
margin-right: 8px;
}
.cl2 {
width: 8px;
height: 30px;
background-color: rgba(174, 214, 255, 1);
margin-right: 8px;
}
.title {
width: 152px;
height: 42px;
text-align: center;
font-size: 32px;
......@@ -50,13 +54,16 @@ const props = defineProps({
font-family: 'Microsoft YaHei';
line-height: 42px;
margin-right: 8px;
width: fit-content;
/* 核心:强制不换行 */
white-space: nowrap;
}
.cl3 {
width: 1367px;
width: 100%;
height: 1px;
background-color: rgba(174, 214, 255, 1);
box-sizing: border-box;
}
}
</style>
......@@ -33,12 +33,9 @@
</li>
<li>
<span class="ul-title">涉及领域:</span>
<div class="ul-tags" v-if="item.AREA">
<span v-for="(field, fIndex) in typeof item.AREA === 'string'
? item.AREA.split(',')
: item.AREA" :key="fIndex" class="ul-pie" :class="'cl' + ((fIndex % 3) + 1)">
{{ field }}
</span>
<div class="ul-tags" v-if="getAreaTagList(item).length">
<AreaTag v-for="(field, fIndex) in getAreaTagList(item)" :key="`${field}-${fIndex}`"
:tagName="field" />
</div>
<span v-else class="ul-content">未知</span>
</li>
......@@ -113,13 +110,8 @@
<RiskSignal :list="riskSignals" @more-click="handleToMoreRiskSignal" postDate="time" name="content"
riskLevel="title" @item-click="handleRiskSignalItemToManage" />
<RiskSignalOverviewDetailDialog
v-model="isRiskOverviewDetailOpen"
:row="riskOverviewDetailRow"
name-field="content"
post-date-field="time"
risk-level-field="title"
/>
<RiskSignalOverviewDetailDialog v-model="isRiskOverviewDetailOpen" :row="riskOverviewDetailRow" name-field="content"
post-date-field="time" risk-level-field="title" />
</div>
</template>
......@@ -132,6 +124,7 @@ import { navigateToViewRiskSignal } from "@/utils/riskSignalOverviewNavigate";
import { getCoopRestrictionTrends, getCoopRestrictionSignals } from "@/api/coopRestriction/coopRestriction.js";
import defaultImg from "./assets/usImg.png";
import CommonPrompt from "../../commonPrompt/index.vue";
import AreaTag from "@/components/base/AreaTag/index.vue";
// 合作限制-查询风险信号数据
const getCoopRestrictionSignalsData = async () => {
......@@ -168,6 +161,20 @@ const getCoopRestrictionTrendsData = async () => {
}
};
const getAreaTagList = (item) => {
const raw = item?.AREA;
if (Array.isArray(raw)) {
return raw.map(v => String(v || "").trim()).filter(Boolean);
}
if (typeof raw === "string") {
return raw
.split(",")
.map(v => String(v || "").trim())
.filter(Boolean);
}
return [];
};
// 轮播图手动切换
const handlePrev = () => {
if (carouselRef.value) {
......@@ -350,7 +357,7 @@ onMounted(() => {
display: flex;
.left-center-main {
width: 439px;
width: 1000dvb;
height: 175px;
position: relative;
......@@ -364,7 +371,7 @@ onMounted(() => {
}
.left-center-main-ul {
width: 439px;
width: 1000px;
height: 132px;
ul {
......@@ -410,6 +417,7 @@ onMounted(() => {
display: flex;
flex-wrap: wrap;
gap: 8px;
width: 600px;
}
.ul-pie {
......
......@@ -74,8 +74,8 @@ import TipTab from "@/views/thinkTank/TipTab/index.vue";
import AiButton from "@/components/base/Ai/AiButton/index.vue";
import AiPane from "@/components/base/Ai/AiPane/index.vue";
const COOP_LEFT_TIP_TEXT = "各类型合作限制政策对比,数据来源:美对华科技合作限制信息平台";
const COOP_RIGHT_TIP_TEXT = "各领域规则分布情况,数据来源:美对华科技合作限制信息平台";
const COOP_LEFT_TIP_TEXT = "数据来源:美对华科技合作限制信息平台";
const COOP_RIGHT_TIP_TEXT = "数据来源:美对华科技合作限制信息平台";
// 临时展示 mock(不改样式):右侧“各领域规则分布情况”
// 用完把这个开关改回 false 即可恢复走接口
......
......@@ -2,21 +2,14 @@
<div class="reslib-page" ref="reslibContainer">
<div class="nav">
<div v-for="item in navList" :key="item.id" class="nav-item" :class="{ active: item.id === activeItem }"
@click="activeItem = item.id">
@click="handleNavItemClick(item.id)">
{{ item.name }}
</div>
</div>
<el-select v-model="sortModel" placeholder="发布时间" class="select" popper-class="coop-select-dropdown"
:teleported="true" placement="bottom-start" :popper-options="sortPopperOptions" @change="handleSortChange">
<template #prefix>
<img v-if="sortModel !== true" src="@/views/thinkTank/ThinkTankDetail/thinkDynamics/images/image down.png"
class="select-prefix-img" alt="" @click.stop="toggleSortPrefix" />
<img v-else src="@/views/thinkTank/ThinkTankDetail/thinkDynamics/images/image up.png" class="select-prefix-img"
alt="" @click.stop="toggleSortPrefix" />
</template>
<el-option :key="true" label="正序" :value="true" />
<el-option :key="false" label="倒序" :value="false" />
</el-select>
<div class="select">
<TimeSortSelectBox :key="`coop-reslib-sort-${activeItem}`" :sort-demension="1"
@handle-px-change="handleCoopReslibPxChange" />
</div>
<div class="main">
<div class="left">
<div class="left-ti1"></div>
......@@ -82,6 +75,7 @@
import { ref, onMounted, watch, computed } from "vue";
import { useRouter } from "vue-router";
import { getCoopRestrictionList } from "@/api/coopRestriction/coopRestriction";
import TimeSortSelectBox from "@/components/base/TimeSortSelectBox/index.vue";
import defaultImg from "../../assets/images/default-icon2.png";
......@@ -172,21 +166,15 @@ const activeItem = ref("0");
/** null:占位「发布时间」且默认倒序;true 正序;false 倒序(显式),与智库概览一致 */
const sort = ref(null);
const sortPopperOptions = {
modifiers: [
{ name: "preventOverflow", options: { mainAxis: false, altAxis: false } },
{ name: "flip", enabled: false }
]
};
const sortModel = computed({
get() {
return sort.value;
},
set(v) {
sort.value = v;
const handleNavItemClick = (id) => {
if (activeItem.value === id) {
return;
}
});
// 切换 tab:默认回到倒序,并从第一页开始
sort.value = null;
currentPage.value = 1;
activeItem.value = id;
};
const handleSortChange = () => {
// 改变排序后从第一页开始
......@@ -197,14 +185,10 @@ const handleSortChange = () => {
}
};
const toggleSortPrefix = () => {
sort.value = sort.value === true ? false : true;
// 切换排序后从第一页开始
if (currentPage.value === 1) {
getMainDataList();
} else {
currentPage.value = 1;
}
/** 合作限制数据库排序公共组件回调:1=时间倒序,2=时间正序(映射到现有 sort(true/false/null)) */
const handleCoopReslibPxChange = (val) => {
sort.value = Number(val) === 2 ? true : false;
handleSortChange();
};
const dataList = ref([
{
......
......@@ -432,9 +432,6 @@ const dataList3 = ref([
padding: 19px 0 20px;
background: rgba(255, 255, 255, 1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
position: sticky;
top: 0;
z-index: 9;
.nav-main {
width: 1600px;
......@@ -442,6 +439,7 @@ const dataList3 = ref([
margin: 0 auto;
display: flex;
align-items: center;
position: relative;
img {
width: 72px;
......@@ -488,8 +486,9 @@ const dataList3 = ref([
display: flex;
justify-content: right;
position: absolute;
bottom: 0;
margin-left: 1224px;
right: 0;
bottom: -20px;
margin-left: 0;
.btn1 {
......
......@@ -34,14 +34,14 @@
</div>
<!-- 数据总览 -->
<div class="datasub" id="position3">
<com-title title="数据总览" />
<com-title title="全景概览" />
<div class="datasub-main">
<dataSub />
</div>
</div>
<!-- 资源库 -->
<div class="reslib" id="position4">
<com-title title="资源库" />
<com-title title="合作限制数据库" />
<div class="reslib-main">
<resLib />
</div>
......
......@@ -304,7 +304,7 @@ const handleGetThinkTankHearingInfo = async () => {
}
};
const REPORT_ANALYSIS_TIP_BOX5 =
"国会听证会关键词云,数据来源:美国兰德公司官网";
"数据来源:美国兰德公司官网";
// 默认仅展示 AiButton,悬停后再请求 AI
const isShowAiContentBox5 = ref(false);
const aiContentBox5 = ref("");
......
......@@ -232,9 +232,6 @@ const handleDownloadDocument = async () => {
border-bottom: 1px solid rgba(234, 236, 238, 1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
position: sticky;
top: 0;
z-index: 99999;
overflow: hidden;
.header-top {
......
<template>
<div class="wrap">
<div class="wrap" ref="pageScrollRef">
<div class="top">
<WarningPane :warnningLevel="riskSignal?.level" :warnningContent="riskSignal?.content" v-if="riskSignal?.level">
</WarningPane>
......@@ -217,7 +217,7 @@ import DefaultIcon1 from '@/assets/icons/default-icon1.png'
import WarningPane from "@/components/base/WarningPane/index.vue"
import WordCloudChart from "@/components/base/WordCloundChart/index.vue"
import SearchContainer from "@/components/SearchContainer.vue";
import { ref, onMounted, computed, defineProps } from "vue";
import { ref, onMounted, computed, defineProps, nextTick } from "vue";
import { ElMessage } from "element-plus";
import {
getThinkTankReportAbstract,
......@@ -258,7 +258,7 @@ const props = defineProps({
}
});
const REPORT_ANALYSIS_TIP_BOX5 =
"智库报告关键词云,数据来源:美国兰德公司官网";
"数据来源:美国兰德公司官网";
// 默认仅展示 AiButton,悬停后再请求 AI
const isShowAiContentBox5 = ref(false);
const aiContentBox5 = ref("");
......@@ -545,8 +545,30 @@ const switchTab = name => {
const currentPage = ref(1);
const pageSize = ref(10);
const total = ref(0);
const pageScrollRef = ref(null);
const getScrollableParent = (el) => {
let cur = el;
while (cur && cur !== document.body && cur !== document.documentElement) {
const style = window.getComputedStyle(cur);
const overflowY = style?.overflowY;
const isScrollable = overflowY === "auto" || overflowY === "scroll";
if (isScrollable && cur.scrollHeight > cur.clientHeight + 1) {
return cur;
}
cur = cur.parentElement;
}
return null;
};
const scrollToTop = async () => {
await nextTick();
const anchor = pageScrollRef.value;
if (!anchor) return;
const scrollEl = getScrollableParent(anchor) || anchor;
scrollEl.scrollTop = 0;
};
const handleCurrentChange = page => {
currentPage.value = page;
scrollToTop();
handleGetThinkTankReportViewpoint();
};
......
......@@ -184,7 +184,7 @@ const applySurveyProjectDocumentTitle = (title) => {
document.title = text;
};
const REPORT_ANALYSIS_TIP_BOX5 =
"调查项目关键词云,数据来源:美国兰德公司官网";
"数据来源:美国兰德公司官网";
// 默认仅展示 AiButton,悬停后再请求 AI
const isShowAiContentBox5 = ref(false);
const aiContentBox5 = ref("");
......
......@@ -149,27 +149,8 @@
</div>
<div class="select-box">
<el-select class="select-box-sort" v-model="sort" placeholder="发布时间" style="width: 120px" :teleported="true"
:placement="'bottom-start'" :popper-options="{
modifiers: [
{
name: 'preventOverflow',
options: { mainAxis: false, altAxis: false }
},
{
name: 'flip',
enabled: false
}
]
}">
<template #prefix>
<img v-if="sort !== true" 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="" />
</template>
<el-option @click="handleGetThinkPolicy()" :key="true" label="正序" :value="true" />
<el-option @click="handleGetThinkPolicy()" :key="false" label="倒序" :value="false" />
</el-select>
<TimeSortSelectBox :key="`policy-tracking-sort-${router.currentRoute.value?.params?.id || ''}`"
:sort-demension="1" @handle-px-change="handlePolicyTrackingPxChange" />
</div>
</div>
<div class="bottom-main">
......@@ -279,8 +260,8 @@
<div class="right-footer">
<div class="info">共{{ total }}条政策建议</div>
<div class="page-box">
<el-pagination :page-size="10" :page-count="pageCount" background layout="prev, pager, next" :total="total"
@current-change="handleCurrentChange" :current-page="currentPage" />
<el-pagination :page-size="10" :page-count="pageCount" background layout="prev, pager, next"
:total="total" @current-change="handleCurrentChange" :current-page="currentPage" />
</div>
</div>
</div>
......@@ -306,6 +287,7 @@ import {
import { getChartAnalysis } from "@/api/aiAnalysis/index";
import AiButton from "@/components/base/Ai/AiButton/index.vue";
import AiPane from "@/components/base/Ai/AiPane/index.vue";
import TimeSortSelectBox from "@/components/base/TimeSortSelectBox/index.vue";
import TipTab from "@/views/thinkTank/TipTab/index.vue";
import defaultNewsIcon from "@/assets/icons/default-icon-news.png";
import AreaTag from "@/components/base/AreaTag/index.vue";
......@@ -353,11 +335,11 @@ const getAreaTagColor = (name, idx = 0) =>
/** 与智库概览 TipTab 文案格式一致(政策追踪-美国国会) */
const POLICY_TRACKING_TIP_BOX1 =
"智库报告中政策建议的领域分布情况,数据来源:美国兰德公司官网";
"数据来源:美国兰德公司官网";
const POLICY_TRACKING_TIP_BOX2 =
"智库报告中政策建议部门分布情况,数据来源:美国兰德公司官网";
"数据来源:美国兰德公司官网";
const POLICY_TRACKING_TIP_BOX3 =
"智库报告热门研究领域变化趋势,数据来源:美国兰德公司官网";
"数据来源:美国兰德公司官网";
/** 筛选「全部」项文案,与市场准入概览-资源库复选逻辑一致 */
const POLICY_FILTER_ALL_AREA = "全部领域";
......@@ -1319,6 +1301,12 @@ const handleSwithSort = () => {
handleGetThinkPolicy();
};
/** 政策追踪排序公共组件回调:1=时间倒序,2=时间正序(映射到现有 sort(true/false/null)) */
const handlePolicyTrackingPxChange = (val) => {
sort.value = Number(val) === 2 ? true : false;
handleGetThinkPolicy();
};
const currentPage = ref(1);
const pageCount = computed(() => {
const size = 10;
......@@ -1610,6 +1598,8 @@ onMounted(async () => {
width: 420px;
height: 22px;
display: flex;
align-items: center;
justify-content: flex-start;
}
.chart-box {
......@@ -1669,10 +1659,13 @@ onMounted(async () => {
.source {
position: absolute;
bottom: 24px;
left: 24px;
width: 420px;
height: 22px;
display: flex;
align-items: center;
justify-content: flex-start;
}
.chart-box {
......@@ -2150,7 +2143,7 @@ onMounted(async () => {
.right {
width: 1224px;
min-height: 1670px;
margin-bottom: 20px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
......@@ -2167,7 +2160,7 @@ onMounted(async () => {
box-sizing: border-box;
padding-left: 37px;
padding-right: 0;
max-height: 1540px;
flex: 1;
.right-empty {
......@@ -2187,7 +2180,7 @@ onMounted(async () => {
padding-left: 37px;
padding-right: 36px;
width: calc(100% + 37px - 36px);
height: 153px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
display: flex;
......
......@@ -120,9 +120,6 @@ onMounted(async () => {
box-shadow: 0 0 20px 0 rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
position: relative;
position: sticky;
top: 0;
z-index: 99999;
overflow: visible;
.header-top {
......
<template>
<div class="wrap">
<div class="wrap" ref="pageScrollRef">
<div class="main-header">
<div class="search-box">
......@@ -19,33 +19,8 @@
<div class="select-box">
<div class="select-box-sort">
<el-select v-model="sort" placeholder="发布时间" style="width: 120px" :teleported="true"
:placement="'bottom-start'" :popper-options="{
modifiers: [
{
name: 'preventOverflow', // 禁用自动翻转逻辑
options: {
mainAxis: false, // 禁用垂直方向的自动调整
altAxis: false, // 禁用水平方向的自动调整
}
},
{
name: 'flip', // 完全禁用翻转功能
enabled: false
}
]
}">
<template #prefix>
<img v-if="sort !== true" src="./images/image down.png" class="select-prefix-img" alt=""
@click.stop="toggleSortAndFetch()" />
<img v-else src="./images/image up.png" class="select-prefix-img" alt=""
@click.stop="toggleSortAndFetch()" />
</template>
<el-option :key="'think-dynamics-sort-asc'" label="正序" :value="true"
@click="handleGetThinkDynamicsReport()" />
<el-option :key="'think-dynamics-sort-desc'" label="倒序" :value="false"
@click="handleGetThinkDynamicsReport()" />
</el-select>
<TimeSortSelectBox :key="`dynamics-sort-${tabResetKey}`" :sort-demension="1"
@handle-px-change="handleDynamicsPxChange" />
</div>
</div>
</div>
......@@ -53,8 +28,7 @@
<ThinkTankReport v-if="isThinkTankReport" :research-type-list="researchTypeList"
:research-time-list="researchTimeList" :key="`智库报告-${tabResetKey}`" :selected-filters="selectedFilters"
:cur-footer-list="curFooterList" :total="total" :current-page="currentPage" :search-keyword="searchReport"
:loading="isThinkTankReportLoading"
@update:selected-filters="handleSelectedFiltersUpdate"
:loading="isThinkTankReportLoading" @update:selected-filters="handleSelectedFiltersUpdate"
@filter-change="(payload) => handleGetThinkDynamicsReport(payload)" @page-change="handleCurrentChange"
@report-click="handleToReportDetail" />
<CongressHearing v-else-if="isCongressHearing" :research-type-list="researchTypeList"
......@@ -76,6 +50,7 @@
<script setup>
import { ref, reactive, onMounted, nextTick } from "vue";
import SurveyForm from "./SurveyForm/index.vue"
import TimeSortSelectBox from "@/components/base/TimeSortSelectBox/index.vue";
// import Img1 from "./images/img1.png";
// import Img2 from "./images/img2.png";
// import Img3 from "./images/img3.png";
......@@ -330,14 +305,37 @@ const handleGetHylyList = async () => {
}
};
const toggleSortAndFetch = async () => {
sort.value = sort.value === true ? false : true;
/** 智库动态排序公共组件回调:1=时间倒序,2=时间正序(映射到现有 sort(true/false/null)) */
const handleDynamicsPxChange = async (val) => {
sort.value = Number(val) === 2 ? true : false;
await handleGetThinkDynamicsReport();
};
const currentPage = ref(1);
const pageScrollRef = ref(null);
const getScrollableParent = (el) => {
let cur = el;
while (cur && cur !== document.body && cur !== document.documentElement) {
const style = window.getComputedStyle(cur);
const overflowY = style?.overflowY;
const isScrollable = overflowY === "auto" || overflowY === "scroll";
if (isScrollable && cur.scrollHeight > cur.clientHeight + 1) {
return cur;
}
cur = cur.parentElement;
}
return null;
};
const scrollToTop = async () => {
await nextTick();
const anchor = pageScrollRef.value;
if (!anchor) return;
const scrollEl = getScrollableParent(anchor) || anchor;
scrollEl.scrollTop = 0;
};
// 处理页码改变事件
const handleCurrentChange = page => {
currentPage.value = page;
scrollToTop();
handleGetThinkDynamicsReport()
};
......@@ -615,14 +613,6 @@ onMounted(async () => {
margin-top: 16px;
display: flex;
.select-box-time,
.select-box-sort {
background: rgb(255, 255, 255);
box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1);
border: 1px solid rgb(230, 231, 232);
border-radius: 4px;
height: 32px;
}
.select-prefix-img {
width: 8px;
......
......@@ -115,7 +115,7 @@
</div>
<div class="source">
<div class="info"><img src="./images/image-exclamation.png"></div>
<div class="text"> 数据来源:美国国会官网,数据时间:2015.1至2025.12</div>
<div class="text"> 数据来源:美国国会官网</div>
</div>
</AnalysisBox>
</div>
......@@ -222,7 +222,7 @@
</div>
<div class="source">
<div class="info"><img src="./images/image-exclamation.png"></div>
<div class="text"> 数据来源:美国国会官网,数据时间:2015.1至2025.12</div>
<div class="text"> 数据来源:美国国会官网</div>
</div>
<div class="middle">
<div class="middle-text">{{ "共" }}{{ personTotal }}{{ "名核心研究人员" }}</div>
......
......@@ -32,7 +32,7 @@ const props = defineProps({
width: 100%;
display: flex;
gap: 8px;
justify-content: center;
justify-content: flex-start;
align-items: center;
height: 22px;
......
......@@ -319,7 +319,8 @@ const handleYearGroupChange = (val) => {
.card-box {
width: 100%;
height: 1134px;
padding-bottom: 32px;
;
display: flex;
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
......@@ -339,7 +340,7 @@ const handleYearGroupChange = (val) => {
.card-content {
width: 1211px;
height: 1067px;
margin-top: 33px;
margin-left: 37px;
......
......@@ -221,7 +221,7 @@
<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>
<DivideHeader id="position3" class="divide-header" :titleText="'全景概览'"></DivideHeader>
<div class="center-footer">
<div class="box5">
<div class="box5-header">
......@@ -253,7 +253,7 @@
<div id="box5Chart" class="box5-chart-canvas"></div>
</div>
<div class="source">
<TipTab :text="'智库报告数量变化趋势,数据来源:美国各智库官网'" />
<TipTab :text="'数据来源:美国各智库官网'" />
</div>
<div class="chart-box">
<div class="btn-box" v-if="!isShowAiContentBox5" @mouseenter="handleSwitchAiContentShowBox5(true)">
......@@ -293,7 +293,7 @@
<template v-else>
<div id="box6Chart"></div>
<div class="source">
<TipTab :text="'智库报告领域分布情况,数据来源:美国各智库官网'" />
<TipTab :text="'数据来源:美国各智库官网'" />
</div>
<div class="chart-box">
<div class="btn-box" v-if="!isShowAiContentBox6" @mouseenter="handleSwitchAiContentShowBox6(true)">
......@@ -325,7 +325,7 @@
<template v-else>
<div id="box7Chart"></div>
<div class="source">
<TipTab :text="'美国科技智库与主要政府机构之间的资金往来,数据来源:美国各智库官网'" />
<TipTab :text="'数据来源:美国各智库官网'" />
</div>
<div class="chart-box">
<div class="btn-box" v-if="!isShowAiContentBox7" @mouseenter="handleSwitchAiContentShowBox7(true)">
......@@ -375,7 +375,7 @@
</div>
<div class="home-main-footer">
<DivideHeader id="position4" class="divide-header" :titleText="'资源库'"></DivideHeader>
<DivideHeader id="position4" class="divide-header" :titleText="'美国科技智库数据库'"></DivideHeader>
<div class="home-main-footer-header">
<div class="btn-box">
......@@ -385,19 +385,8 @@
</div>
</div>
<div class="select-box">
<el-select v-model="resourceLibrarySortModel" class="resource-library-sort-select" placeholder="发布时间"
style="width: 120px" :teleported="true" placement="bottom-start"
:popper-options="resourceLibrarySortPopperOptions" @change="handleResourceLibrarySortChange">
<template #prefix>
<img v-if="resourceLibrarySortModel !== true"
src="@/views/thinkTank/ThinkTankDetail/thinkDynamics/images/image down.png"
class="resource-library-sort-prefix-img" alt="" @click.stop="toggleResourceLibrarySortPrefix" />
<img v-else src="@/views/thinkTank/ThinkTankDetail/thinkDynamics/images/image up.png"
class="resource-library-sort-prefix-img" alt="" @click.stop="toggleResourceLibrarySortPrefix" />
</template>
<el-option :key="'resource-lib-sort-asc'" label="正序" :value="true" />
<el-option :key="'resource-lib-sort-desc'" label="倒序" :value="false" />
</el-select>
<TimeSortSelectBox :key="`reslib-sort-${resourceTabResetKey}`" :sort-demension="1"
@handle-px-change="handleResourceLibraryPxChange" />
</div>
<!-- <el-select v-model="sort" placeholder="发布时间" style="width: 120px; margin-left: 8px">
<el-option @click="handleGetetThinkTankReport()" :key="true" label="正序" :value="true" />
......@@ -409,29 +398,28 @@
v-model:selectedAreaList="selectedAreaList" :pub-time-list="pubTimeList"
v-model:selectedPubTimeList="selectedPubTimeList" @filter-change="handleThinkTankReportFilterChange"
:cur-footer-list="curFooterList" :total="total" :current-page="currentPage"
:loading="isResourceReportLoading"
@report-click="handleToReportDetail" @page-change="handleCurrentChange" />
:loading="isResourceReportLoading" @report-click="handleToReportDetail"
@page-change="handleCurrentChange" />
<HomeMainFooterSurvey v-else-if="activeCate === '调查项目'" :area-list="areaList"
v-model:selectedAreaList="surveySelectedAreaList" :pub-time-list="pubTimeList"
v-model:selectedPubTimeList="surveySelectedPubTimeList" @filter-change="handleSurveyFilterChange"
:cur-footer-list="surveyFooterList" :total="surveyTotal" :current-page="surveyCurrentPage"
:loading="isResourceSurveyLoading"
@report-click="handleToSurveyProjectView" @page-change="handleSurveyCurrentChange" />
:loading="isResourceSurveyLoading" @report-click="handleToSurveyProjectView"
@page-change="handleSurveyCurrentChange" />
<ThinkTankCongressHearingOverview v-else-if="activeCate === '国会听证会'" :key="`congress-${resourceTabResetKey}`"
:hearing-data="hearingData" :research-type-list="areaList" :research-time-list="pubTimeList"
v-model:selectedAreaList="congressSelectedAreaList"
v-model:selectedPubTimeList="congressSelectedPubTimeList" :total="congressTotal"
:current-page="congressCurrentPage" @filter-change="handleCongressFilterChange"
:loading="isResourceHearingLoading"
@page-change="handleCongressCurrentChange" @report-click="handleToHearingDetail" />
:loading="isResourceHearingLoading" @page-change="handleCongressCurrentChange"
@report-click="handleToHearingDetail" />
<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"
:loading="isResourcePolicyLoading"
@page-change="handlePolicyCurrentChange" />
:loading="isResourcePolicyLoading" @page-change="handlePolicyCurrentChange" />
</div>
</div>
......@@ -477,6 +465,7 @@ import getPieChart from "./utils/piechart";
import { MUTICHARTCOLORS } from "@/common/constant.js";
import getSankeyChart from "./utils/sankey";
import { getChartAnalysis } from "@/api/aiAnalysis/index";
import TimeSortSelectBox from "@/components/base/TimeSortSelectBox/index.vue";
import defaultNewsIcon from "@/assets/icons/default-icon-news.png";
import defaultHeaderIcin from "@/assets/icons/default-icon1.png";
import News1 from "./assets/images/news1.png";
......@@ -1997,6 +1986,14 @@ const toggleResourceLibrarySortPrefix = () => {
}
};
/** 资源库排序公共组件回调:1=时间倒序,2=时间正序(与现有 sort(true/false/null) 映射) */
const handleResourceLibraryPxChange = (val) => {
// 组件默认值为 1(时间倒序),这里保持与旧逻辑一致:倒序用 false,正序用 true
const mapped = Number(val) === 2 ? true : false;
resourceLibrarySortModel.value = mapped;
handleResourceLibrarySortChange();
};
/** 与调查项目 surveyFooterList 一致:初始空列表,由接口填充;失败或非 200 时清空 */
const curFooterList = ref([]);
const currentPage = ref(1);
......
......@@ -309,8 +309,9 @@ onMounted(async () => {
<style lang="scss" scoped>
.wrap {
overflow-y: auto;
height: 100vh;
overflow-y: auto;
overflow-x: hidden;
.header {
......@@ -320,9 +321,6 @@ onMounted(async () => {
border-bottom: 1px solid rgba(234, 236, 238, 1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 1);
position: sticky;
top: 0;
z-index: 99999;
overflow: hidden;
.header-top {
......@@ -703,7 +701,6 @@ onMounted(async () => {
height: 881px;
display: flex;
overflow-y: auto;
/* 右侧统一滚动条,控制两侧原文+译文一起滚动 */
overflow-x: hidden;
}
......
......@@ -5,7 +5,7 @@
<div class="center-center">
<div class="center-header">
<div class="center-header-left">
<img class="iconstyle" src="./assets/images/warning.svg" />
<img class="iconstyle" src="./assets/images/warning-red.svg" />
<div class="center-header-title">风险信号管理</div>
</div>
<div class="center-header-right">
......@@ -16,7 +16,7 @@
<div class="center-middle">
<div class="center-middle-left">
<div class="lineitem">
<div class="item">
<div class="item item--shift-left">
<div class="top">
<div class="dot" style="background-color: rgba(95, 101, 108, 1)"></div>
<div class="text1">本年新增风险</div>
......@@ -36,7 +36,7 @@
</div>
</div>
<div class="lineitem">
<div class="item">
<div class="item item--shift-left">
<div class="top">
<div class="dot" style="background-color: rgba(5, 95, 194, 1)"></div>
<div class="text1">已处理风险</div>
......@@ -50,7 +50,7 @@
<div class="text1">待处理风险</div>
</div>
<div class="text2" style="color: rgba(206, 79, 81, 1)">
<span class="text2-inner">{{ basicInfo.pendingCount + " 项" }}</span>
<span class="text2-inner">{{ formatThousands(basicInfo.pendingCount) + " 项" }}</span>
</div>
</div>
</div>
......@@ -213,7 +213,7 @@
</div>
<div class="right-footer">
<div class="footer-left">
{{ `共 ${totalNum} 项调查` }}
{{ `共 ${formatThousands(totalNum)} 项调查` }}
</div>
<div class="footer-right">
<el-pagination @current-change="handleCurrentChange" :pageSize="pageSize" :current-page="currentPage"
......@@ -233,7 +233,7 @@
<el-dialog v-model="isRiskDetailVisible" class="risk-signal-detail-dialog" modal-class="risk-signal-detail-modal"
width="1280px" align-center :show-close="true" destroy-on-close @closed="handleCloseRiskDetail">
<template #header>
<img class="header-icon" src="./assets/images/risk-icon.png" alt="" />
<img class="header-icon" :src="riskDetailHeaderIconSrc" alt="" />
<span v-if="riskDetailListLevelText" class="risk-signal-detail-dialog__level"
:class="riskDetailListLevelModifierClass">{{ riskDetailListLevelText }}</span>
<div v-if="riskDetailBodyFromApi" class="risk-signal-detail-dialog__read-indicator">
......@@ -597,6 +597,15 @@ const riskDetailListLevelModifierClass = computed(
() => `risk-signal-detail-dialog__level--${getRiskDetailLevelModifier(riskDetailListLevelText.value)}`
);
const riskDetailHeaderIconSrc = computed(() => {
const key = getRiskListItemLevelKey(riskDetailListLevelText.value);
if (key === "lv1") return new URL("./assets/images/risk-icon-red.png", import.meta.url).href;
if (key === "lv2") return new URL("./assets/images/risk-icon-orange.png", import.meta.url).href;
if (key === "lv3") return new URL("./assets/images/risk-icon-yellow.png", import.meta.url).href;
if (key === "lv4") return new URL("./assets/images/risk-icon-green.png", import.meta.url).href;
return new URL("./assets/images/risk-icon-blue.png", import.meta.url).href;
});
/** 列表项风险等级样式键:与 `@/components/base/riskSignal` itemLeftStatus1~5 一致 */
const getRiskListItemLevelKey = (level) => {
const t = String(level ?? "").trim();
......@@ -623,6 +632,12 @@ const isRiskLevelNoData = (level) => {
const route = useRoute();
const router = useRouter();
const formatThousands = (val) => {
const n = Number(val ?? 0);
if (!Number.isFinite(n)) return "0";
return new Intl.NumberFormat("en-US").format(n);
};
const consumeOpenFirstDetailFromQuery = async () => {
if (route.query[OPEN_FIRST_RISK_DETAIL_QUERY_KEY] !== "1") {
return;
......@@ -1095,6 +1110,10 @@ onMounted(async () => {
unicode-bidi: isolate;
}
}
.item--shift-left {
transform: translateX(-20px);
}
}
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论