|
|
@@ -1,14 +1,18 @@
|
|
|
<template>
|
|
|
<div class="collectpage">
|
|
|
-
|
|
|
<!-- 主要内容 -->
|
|
|
- <div class="main-content">
|
|
|
+ <div class="main-content">
|
|
|
<!-- 搜索输入框 -->
|
|
|
<div class="search-container">
|
|
|
<div class="search-wrapper">
|
|
|
<!-- 搜索输入框和检索按钮 -->
|
|
|
<div class="search-input-wrapper">
|
|
|
- <el-input v-model="searchParams.searchText" placeholder="请输入关键词..." class="search-input cut-corner-input" @keyup.enter="quickSearch">
|
|
|
+ <el-input
|
|
|
+ v-model="searchParams.searchText"
|
|
|
+ placeholder="请输入关键词..."
|
|
|
+ class="search-input cut-corner-input"
|
|
|
+ @keyup.enter="quickSearch"
|
|
|
+ >
|
|
|
<template #suffix>
|
|
|
<el-button @click="quickSearch" class="quick-search-btn">
|
|
|
<img src="@/assets/img/icon_search.png" alt="检索" class="search-icon" />
|
|
|
@@ -57,12 +61,12 @@
|
|
|
import { ref, onMounted, nextTick } from 'vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
|
import getBookCountApi from '@/api'
|
|
|
-import { addWatermarkToCollectionImage } from "@/utils/index.js";
|
|
|
+import { addWatermarkToCollectionImage } from '@/utils/index.js'
|
|
|
|
|
|
defineOptions({
|
|
|
- name: 'CollectPage'
|
|
|
+ name: 'CollectPage',
|
|
|
})
|
|
|
-const imgUrl = import.meta.env.VITE_MODEL_URL;
|
|
|
+const imgUrl = import.meta.env.VITE_MODEL_URL
|
|
|
const router = useRouter()
|
|
|
|
|
|
// 响应式数据
|
|
|
@@ -80,54 +84,54 @@ const hasMoreData = ref(true) // 是否还有更多数据
|
|
|
const resultsContainer = ref(null)
|
|
|
const STORAGE_KEY = 'collectPageState'
|
|
|
// 处理图片水印
|
|
|
-const watermarkedImages = ref(new Map()); // 存储处理后的水印图片
|
|
|
+const watermarkedImages = ref(new Map()) // 存储处理后的水印图片
|
|
|
const processImageWithWatermark = async (item) => {
|
|
|
// 如果已经处理过,直接返回
|
|
|
if (watermarkedImages.value.has(item.id)) {
|
|
|
// console.log('图片已处理过,直接返回缓存结果');
|
|
|
- return watermarkedImages.value.get(item.id);
|
|
|
+ return watermarkedImages.value.get(item.id)
|
|
|
}
|
|
|
// 如果正在处理,避免重复处理
|
|
|
if (item.watermarkProcessing) {
|
|
|
- return item.originalImage;
|
|
|
+ return item.originalImage
|
|
|
}
|
|
|
try {
|
|
|
// 标记为处理中
|
|
|
- item.watermarkProcessing = true;
|
|
|
+ item.watermarkProcessing = true
|
|
|
// 处理水印
|
|
|
const watermarkedImageUrl = await addWatermarkToCollectionImage(item.originalImage, {
|
|
|
position: 'center',
|
|
|
opacity: 1,
|
|
|
scale: 0.5,
|
|
|
- margin: 15
|
|
|
- });
|
|
|
+ margin: 15,
|
|
|
+ })
|
|
|
// 存储处理后的图片
|
|
|
- watermarkedImages.value.set(item.id, watermarkedImageUrl);
|
|
|
+ watermarkedImages.value.set(item.id, watermarkedImageUrl)
|
|
|
// 更新图片地址
|
|
|
- item.image = watermarkedImageUrl;
|
|
|
- return watermarkedImageUrl;
|
|
|
+ item.image = watermarkedImageUrl
|
|
|
+ return watermarkedImageUrl
|
|
|
} catch (error) {
|
|
|
- console.error('水印处理失败:', error);
|
|
|
+ console.error('水印处理失败:', error)
|
|
|
// 统一处理:失败时直接缓存并返回原图
|
|
|
- watermarkedImages.value.set(item.id, item.originalImage);
|
|
|
- item.image = item.originalImage;
|
|
|
- return item.originalImage;
|
|
|
+ watermarkedImages.value.set(item.id, item.originalImage)
|
|
|
+ item.image = item.originalImage
|
|
|
+ return item.originalImage
|
|
|
} finally {
|
|
|
// 标记处理完成
|
|
|
- item.watermarkProcessing = false;
|
|
|
+ item.watermarkProcessing = false
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
// 获取图片地址(带水印处理)
|
|
|
const getImageUrl = (item) => {
|
|
|
// 如果已经有水印图片,直接返回
|
|
|
if (watermarkedImages.value.has(item.id)) {
|
|
|
- return watermarkedImages.value.get(item.id);
|
|
|
+ return watermarkedImages.value.get(item.id)
|
|
|
}
|
|
|
// 异步处理水印
|
|
|
- processImageWithWatermark(item);
|
|
|
+ processImageWithWatermark(item)
|
|
|
// 先返回原图
|
|
|
- return item.originalImage;
|
|
|
-};
|
|
|
+ return item.originalImage
|
|
|
+}
|
|
|
const savePageState = () => {
|
|
|
try {
|
|
|
const scrollTop = resultsContainer.value ? resultsContainer.value.scrollTop || 0 : 0
|
|
|
@@ -136,7 +140,7 @@ const savePageState = () => {
|
|
|
searchResults: [...searchResults.value],
|
|
|
currentPage: currentPage.value,
|
|
|
hasMoreData: hasMoreData.value,
|
|
|
- scrollTop
|
|
|
+ scrollTop,
|
|
|
}
|
|
|
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state))
|
|
|
} catch {
|
|
|
@@ -166,7 +170,6 @@ const restorePageStateIfAvailable = async () => {
|
|
|
return true
|
|
|
}
|
|
|
|
|
|
-
|
|
|
// 快速搜索(回车键触发)
|
|
|
const quickSearch = () => {
|
|
|
console.log('searchParams', searchParams.value)
|
|
|
@@ -175,30 +178,30 @@ const quickSearch = () => {
|
|
|
|
|
|
// 加载藏品数据
|
|
|
const loadArtifactsData = async (isLoadMore = false) => {
|
|
|
- if (loading.value) return;
|
|
|
+ if (loading.value) return
|
|
|
|
|
|
- loading.value = true;
|
|
|
+ loading.value = true
|
|
|
try {
|
|
|
const searchObj = {
|
|
|
searchText: searchParams.value.searchText,
|
|
|
pageNo: currentPage.value,
|
|
|
- pageSize: pageSize
|
|
|
- };
|
|
|
+ pageSize: pageSize,
|
|
|
+ }
|
|
|
|
|
|
// 调用API获取数据
|
|
|
- const response = await getBookCountApi.getNewsListApi(searchObj);
|
|
|
+ const response = await getBookCountApi.getNewsListApi(searchObj)
|
|
|
|
|
|
// 处理返回的数据
|
|
|
- const artifacts = response.pageData || [];
|
|
|
+ const artifacts = response.pageData || []
|
|
|
|
|
|
if (artifacts.length === 0) {
|
|
|
- hasMoreData.value = false;
|
|
|
- loading.value = false;
|
|
|
- return;
|
|
|
+ hasMoreData.value = false
|
|
|
+ loading.value = false
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
// 数据格式化处理
|
|
|
- const processedArtifacts = artifacts.map(item => ({
|
|
|
+ const processedArtifacts = artifacts.map((item) => ({
|
|
|
id: item.id,
|
|
|
contentType: item.contentType || '富文本编辑',
|
|
|
name: item.name || item.title,
|
|
|
@@ -210,57 +213,61 @@ const loadArtifactsData = async (isLoadMore = false) => {
|
|
|
image: `${imgUrl}${item.thumbnail}`,
|
|
|
originalImage: `${imgUrl}${item.thumbnail}`,
|
|
|
isLoading: true,
|
|
|
- ...item
|
|
|
- }));
|
|
|
+ ...item,
|
|
|
+ }))
|
|
|
|
|
|
if (isLoadMore) {
|
|
|
// 追加数据
|
|
|
- searchResults.value.push(...processedArtifacts);
|
|
|
+ searchResults.value.push(...processedArtifacts)
|
|
|
} else {
|
|
|
// 重新加载
|
|
|
- searchResults.value = processedArtifacts;
|
|
|
+ searchResults.value = processedArtifacts
|
|
|
}
|
|
|
|
|
|
// 延迟触发瀑布效果 - 使用 AnnouncementContent 的动画时机
|
|
|
setTimeout(() => {
|
|
|
processedArtifacts.forEach((item, index) => {
|
|
|
- setTimeout(() => {
|
|
|
- const foundItem = searchResults.value.find(listItem => listItem.id === item.id && listItem.isLoading);
|
|
|
- if (foundItem) {
|
|
|
- foundItem.isLoading = false;
|
|
|
- }
|
|
|
- }, index * 200 + 300); // 使用与 AnnouncementContent 相同的时机
|
|
|
- });
|
|
|
- }, 200);
|
|
|
+ setTimeout(
|
|
|
+ () => {
|
|
|
+ const foundItem = searchResults.value.find(
|
|
|
+ (listItem) => listItem.id === item.id && listItem.isLoading,
|
|
|
+ )
|
|
|
+ if (foundItem) {
|
|
|
+ foundItem.isLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ index * 200 + 300,
|
|
|
+ ) // 使用与 AnnouncementContent 相同的时机
|
|
|
+ })
|
|
|
+ }, 200)
|
|
|
|
|
|
// 检查是否还有更多数据
|
|
|
if (artifacts.length < pageSize) {
|
|
|
- hasMoreData.value = false;
|
|
|
+ hasMoreData.value = false
|
|
|
}
|
|
|
-
|
|
|
} catch (error) {
|
|
|
- console.error('获取藏品数据失败:', error);
|
|
|
- searchResults.value = [];
|
|
|
- searched.value = true;
|
|
|
+ console.error('获取藏品数据失败:', error)
|
|
|
+ searchResults.value = []
|
|
|
+ searched.value = true
|
|
|
} finally {
|
|
|
- loading.value = false;
|
|
|
+ loading.value = false
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
// 处理搜索
|
|
|
const handleSearch = async () => {
|
|
|
- console.log('执行搜索:', searchParams.value.searchText);
|
|
|
- currentPage.value = 1;
|
|
|
- searchResults.value = [];
|
|
|
- hasMoreData.value = true;
|
|
|
- searched.value = true;
|
|
|
- await loadArtifactsData();
|
|
|
+ console.log('执行搜索:', searchParams.value.searchText)
|
|
|
+ currentPage.value = 1
|
|
|
+ searchResults.value = []
|
|
|
+ hasMoreData.value = true
|
|
|
+ searched.value = true
|
|
|
+ await loadArtifactsData()
|
|
|
}
|
|
|
|
|
|
// 查看详情
|
|
|
const viewDetails = (item) => {
|
|
|
console.log('item', item)
|
|
|
- if(item.contentType == '公众号链接'){
|
|
|
+ if (item.contentType == '公众号链接') {
|
|
|
// 离开前保存列表与滚动状态
|
|
|
console.log('公众号链接', item.content)
|
|
|
savePageState()
|
|
|
@@ -276,47 +283,52 @@ const viewDetails = (item) => {
|
|
|
if (document && document.body) {
|
|
|
document.body.scrollTop = 0
|
|
|
}
|
|
|
- } catch { /* ignore */ }
|
|
|
+ } catch {
|
|
|
+ /* ignore */
|
|
|
+ }
|
|
|
window.location.href = item.content
|
|
|
// scrollTop
|
|
|
// const a = document.createElement('a')
|
|
|
// a.href = item.content
|
|
|
// a.target = '_blank'
|
|
|
// a.click()
|
|
|
- } else{
|
|
|
+ } else {
|
|
|
// 前往详情前保存状态,返回时恢复
|
|
|
savePageState()
|
|
|
router.push({
|
|
|
path: '/contentDetail',
|
|
|
query: {
|
|
|
- id: item.id
|
|
|
- }
|
|
|
+ id: item.id,
|
|
|
+ },
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 滚动处理 - 加载更多
|
|
|
const handleScroll = async (event) => {
|
|
|
- const container = event.target;
|
|
|
- if (!container || loading.value || !hasMoreData.value) return;
|
|
|
+ const container = event.target
|
|
|
+ if (!container || loading.value || !hasMoreData.value) return
|
|
|
|
|
|
// 检查是否滚动到底部
|
|
|
- const isScrolledToBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - 50;
|
|
|
+ const isScrolledToBottom =
|
|
|
+ container.scrollTop + container.clientHeight >= container.scrollHeight - 50
|
|
|
|
|
|
if (isScrolledToBottom) {
|
|
|
- console.log('开始加载更多藏品数据...');
|
|
|
- currentPage.value++;
|
|
|
- await loadArtifactsData(true);
|
|
|
+ console.log('开始加载更多藏品数据...')
|
|
|
+ currentPage.value++
|
|
|
+ await loadArtifactsData(true)
|
|
|
}
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
// 组件挂载
|
|
|
onMounted(async () => {
|
|
|
- console.log('内容页组件已挂载');
|
|
|
+ console.log('内容页组件已挂载')
|
|
|
if ('scrollRestoration' in history) {
|
|
|
try {
|
|
|
history.scrollRestoration = 'manual'
|
|
|
- } catch { /* ignore */ }
|
|
|
+ } catch {
|
|
|
+ /* ignore */
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 优先尝试恢复上次状态,若没有再加载初始数据
|
|
|
@@ -324,8 +336,8 @@ onMounted(async () => {
|
|
|
if (!restored) {
|
|
|
// 延迟加载初始数据,确保DOM已渲染
|
|
|
setTimeout(() => {
|
|
|
- loadArtifactsData();
|
|
|
- }, 100);
|
|
|
+ loadArtifactsData()
|
|
|
+ }, 100)
|
|
|
}
|
|
|
})
|
|
|
</script>
|
|
|
@@ -443,7 +455,7 @@ onMounted(async () => {
|
|
|
border: none;
|
|
|
background: url('@/assets/img/btn_active.png') no-repeat;
|
|
|
background-size: 30px 30px;
|
|
|
- .search-icon{
|
|
|
+ .search-icon {
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
@@ -481,7 +493,7 @@ onMounted(async () => {
|
|
|
gap: 2px;
|
|
|
border: none;
|
|
|
border-radius: 4px;
|
|
|
- color: #B49D7E;
|
|
|
+ color: #b49d7e;
|
|
|
font-size: 16px;
|
|
|
font-weight: 500;
|
|
|
cursor: pointer;
|
|
|
@@ -539,10 +551,13 @@ onMounted(async () => {
|
|
|
|
|
|
// 瀑布加载状态
|
|
|
&.loading-waterfall {
|
|
|
- .result-image, .result-info {
|
|
|
+ .result-image,
|
|
|
+ .result-info {
|
|
|
opacity: 0.3;
|
|
|
filter: grayscale(100%);
|
|
|
- transition: opacity 0.3s ease, filter 0.3s ease;
|
|
|
+ transition:
|
|
|
+ opacity 0.3s ease,
|
|
|
+ filter 0.3s ease;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -552,19 +567,22 @@ onMounted(async () => {
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
- background: linear-gradient(180deg,
|
|
|
+ background: linear-gradient(
|
|
|
+ 180deg,
|
|
|
rgba(0, 0, 0, 0.9) 0%,
|
|
|
rgba(0, 0, 0, 0.8) 50%,
|
|
|
- rgba(0, 0, 0, 0.9) 100%);
|
|
|
+ rgba(0, 0, 0, 0.9) 100%
|
|
|
+ );
|
|
|
z-index: 10;
|
|
|
transform: translateY(-100%);
|
|
|
border-radius: 8px;
|
|
|
- animation: waterfallDown 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards,
|
|
|
- waterfallUp 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.8s forwards;
|
|
|
+ animation:
|
|
|
+ waterfallDown 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards,
|
|
|
+ waterfallUp 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.8s forwards;
|
|
|
will-change: transform, opacity;
|
|
|
}
|
|
|
}
|
|
|
-.result-image-wrapper{
|
|
|
+.result-image-wrapper {
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
width: 170px;
|
|
|
@@ -578,7 +596,9 @@ onMounted(async () => {
|
|
|
object-fit: cover;
|
|
|
flex-shrink: 0;
|
|
|
border-radius: 6px;
|
|
|
- transition: opacity 0.3s ease, filter 0.3s ease;
|
|
|
+ transition:
|
|
|
+ opacity 0.3s ease,
|
|
|
+ filter 0.3s ease;
|
|
|
}
|
|
|
|
|
|
.result-info {
|
|
|
@@ -586,7 +606,9 @@ onMounted(async () => {
|
|
|
// display: flex;
|
|
|
// flex-direction: column;
|
|
|
// justify-content: center;
|
|
|
- transition: opacity 0.3s ease, filter 0.3s ease;
|
|
|
+ transition:
|
|
|
+ opacity 0.3s ease,
|
|
|
+ filter 0.3s ease;
|
|
|
position: relative;
|
|
|
padding-bottom: 30px;
|
|
|
|
|
|
@@ -621,7 +643,7 @@ onMounted(async () => {
|
|
|
height: 30px;
|
|
|
line-height: 30px;
|
|
|
text-align: center;
|
|
|
- color: #A99271;
|
|
|
+ color: #a99271;
|
|
|
font-size: 12px;
|
|
|
padding: 0 10px;
|
|
|
}
|