提交 a0f68572 authored 作者: 刘宇琪's avatar 刘宇琪

fix:科技人物问题发现

上级 3cbf1533
......@@ -10,7 +10,10 @@
:total="total"
:current-page="currentPage"
:page-size="10"
:keyword="searchKeyword"
:loading="loading"
@page-change="handlePageChange"
@search="handleSearch"
/>
</div>
</div>
......@@ -30,22 +33,33 @@ const newsList = ref([])
const total = ref(0)
const currentPage = ref(1)
const keywords = ref([])
const searchKeyword = ref('')
const loading = ref(false)
const COLORS = ['red', 'cyan', 'gold', 'blue', 'volcano']
async function loadNews(page = 1) {
if (!personId.value) return
loading.value = true
currentPage.value = page
const res = await getPotentialNewsList(personId.value, {
const params = {
currentPage: page - 1,
pageSize: 10,
})
if (res.code === 200 && res.data) {
newsList.value = res.data.content || []
total.value = res.data.totalElements || 0
} else {
newsList.value = []
total.value = 0
}
if (searchKeyword.value) {
params.searchText = searchKeyword.value
}
try {
const res = await getPotentialNewsList(personId.value, params)
if (res.code === 200 && res.data) {
newsList.value = res.data.content || []
total.value = res.data.totalElements || 0
} else {
newsList.value = []
total.value = 0
}
} finally {
loading.value = false
}
}
......@@ -65,6 +79,11 @@ async function handlePageChange(page) {
await loadNews(page)
}
async function handleSearch(keyword) {
searchKeyword.value = keyword
await loadNews(1)
}
onMounted(async () => {
if (!personId.value) return
await Promise.all([loadNews(), loadKeywords()])
......
......@@ -6,7 +6,7 @@
<svg class="pna-header-icon" width="8" height="20" viewBox="0 0 8 20" fill="none">
<rect width="8" height="20" rx="2" fill="rgba(5,95,194,1)" />
</svg>
<span class="pna-header-title">潜在提案主题分析</span>
<span class="pna-header-title">潜在提案词云分析</span>
</div>
<div class="pna-header-actions">
<!-- 下载图标 (9_1305): 竖线 + 向下箭头 + 底座 -->
......
......@@ -2,6 +2,7 @@
<div class="pn-list-container">
<div v-if="loading" class="pn-loading-mask">
<div class="pn-spinner"></div>
<span class="pn-loading-text">加载中...</span>
</div>
<div class="pn-header">
<div class="pn-header-left">
......@@ -24,8 +25,13 @@
<div class="pn-search-wrapper">
<div class="pn-search">
<span class="pn-search-placeholder">{{ keyword || '搜索新闻' }}</span>
<svg class="pn-search-icon" width="16" height="16" viewBox="0 0 16 16" fill="none">
<input
class="pn-search-input"
v-model="searchText"
placeholder="搜索提案"
@input="handleSearch"
/>
<svg class="pn-search-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" @click="handleSearch" style="cursor: pointer">
<circle cx="7" cy="7" r="5.5" stroke="rgba(132,136,142,1)" stroke-width="1.2" fill="none" />
<path d="M11 11L14 14" stroke="rgba(132,136,142,1)" stroke-width="1.2" stroke-linecap="round" />
</svg>
......@@ -33,11 +39,7 @@
</div>
<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" />
<el-empty v-if="!loading && newsList.length === 0" description="暂无数据" :image-size="80" />
<div
v-for="(item, index) in newsList"
v-show="!loading"
......@@ -54,7 +56,7 @@
</div>
<div class="pn-footer" v-if="newsList.length > 0">
<span class="pn-footer-total">{{ total }}关键新闻</span>
<span class="pn-footer-total">{{ total }}</span>
<div class="pn-pagination">
<button
class="pn-page-btn pn-page-prev"
......@@ -86,7 +88,7 @@
</template>
<script setup>
import { computed } from 'vue'
import { computed, ref } from 'vue'
import TagBadge from './TagBadge.vue'
const tagColorMap = {
......@@ -103,7 +105,17 @@ const props = defineProps({
loading: { type: Boolean, default: false },
})
defineEmits(['page-change'])
const searchText = ref(props.keyword)
const emit = defineEmits(['page-change', 'search'])
let debounceTimer = null
function handleSearch() {
clearTimeout(debounceTimer)
debounceTimer = setTimeout(() => {
emit('search', searchText.value)
}, 300)
}
const totalPages = computed(() => Math.max(1, Math.ceil(props.total / props.pageSize)))
......@@ -131,6 +143,7 @@ const displayedPages = computed(() => {
border: 1px solid rgba(234, 236, 238, 1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
overflow: hidden;
position: relative;
}
.pn-header {
......@@ -186,6 +199,19 @@ const displayedPages = computed(() => {
color: rgba(132, 136, 142, 1);
font-family: 'Source Han Sans CN', 'Noto Sans SC', sans-serif;
}
.pn-search-input {
flex: 1;
border: none;
outline: none;
font-size: 16px;
line-height: 24px;
color: rgba(59, 65, 75, 1);
font-family: 'Source Han Sans CN', 'Noto Sans SC', sans-serif;
background: transparent;
}
.pn-search-input::placeholder {
color: rgba(132, 136, 142, 1);
}
.pn-search-icon {
flex-shrink: 0;
}
......@@ -346,14 +372,22 @@ const displayedPages = computed(() => {
.pn-loading-mask {
position: absolute;
inset: 0;
background: rgba(255, 255, 255, 0.6);
background: rgba(255, 255, 255, 0.7);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 100;
backdrop-filter: blur(2px);
}
.pn-loading-text {
margin-top: 8px;
font-size: 14px;
color: rgba(22, 119, 255, 1);
font-family: 'Microsoft YaHei', sans-serif;
}
.pn-spinner {
width: 40px;
height: 40px;
......
......@@ -61,6 +61,8 @@ const props = defineProps({
watch(
() => props.typeId,
val => {
// 切换tab时,恢复该tab之前记住的页数
currentPage.value = pageMap[val] || 1;
handlegetPersonResourceFn();
}
);
......@@ -73,6 +75,8 @@ const loading = ref(false);
const abortController = ref(null);
const currentPage = ref(1);
const PersonResource = ref([]);
// 每个tab记住各自的页数
const pageMap = {};
// 获取人物资源库
const handlegetPersonResourceFn = async () => {
// 取消上一次未完成的请求
......@@ -123,6 +127,8 @@ const handlegetPersonResourceFn = async () => {
// 处理页码改变事件
const handleCurrentChange = page => {
currentPage.value = page;
// 记住当前tab的页数
pageMap[props.typeId] = page;
handlegetPersonResourceFn();
};
......
......@@ -129,7 +129,7 @@
<div class="timeline-wrapper">
<el-timeline>
<el-timeline-item
v-for="(activity, index) in person.newsList"
v-for="(activity, index) in person.newsList.slice(0, 3)"
:key="index" placement="top" type="primary"
:hollow="true">
<template #dot>
......@@ -2140,6 +2140,12 @@ onMounted(async () => {
:deep(.el-timeline-item__content) {
margin-left: 10px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
}
:deep(.el-timeline-item__wrapper) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论