2025-08-26 16:43:41 +08:00

304 lines
8.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="followBox">
<div class="followBox-title">
<span>我的</span>
<span class="hightText">关注</span>
</div>
<div class="radio-group">
<label class="radio-item" style="margin-right: 25px;" :class="{ active: publish_type === '1' }">
<input type="radio" v-model="publish_type" value="1" @change="handleTypeChange">
<span class="radio-text">企业商品</span>
</label>
<label class="radio-item" :class="{ active: publish_type === '2' }">
<input type="radio" v-model="publish_type" value="2" @change="handleTypeChange">
<span class="radio-text">企业需求</span>
</label>
</div>
<div v-loading="loadingBox" class="history-list" v-if="productList.length > 0">
<div class="history-item" v-for="item in productList" :key="item.id">
<div class="history-date">
<span class="date-text">{{ formatBrowseDate(item.browse_date) }}</span>
<span class="relative-time">{{ getRelativeTime(item.browse_date) }}</span>
</div>
<div class="history-content">
<productCard
contentType="favorite"
:productList="item.products"
:type="publish_type == '1' ? 'homePage' : 'supplyAndDemandSquare'"
@delete-item="handleDeleteItem">
</productCard>
</div>
</div>
</div>
<div class="empty-state" v-else>
<div class="empty-icon">📋</div>
<div class="empty-text">暂无关注记录</div>
</div>
</div>
</template>
<script>
import { reqFavoriteSearch } from '@/api/ncmatch';
import productCard from '../mainPage/productCard/index.vue';
import { formatBrowseDate, getRelativeTime } from './tool.js';
export default {
name: 'followBox',
data() {
return {
loadingBox:false,
productList: [],
value1: null,
publish_type: '1', // 默认选择企业商品
myProductList: [
]
}
},
created() {
this.reqFavoriteSearch();
},
components: {
productCard
},
methods: {
formatBrowseDate,
getRelativeTime,
handleTypeChange() {
// 当类型改变时重新获取数据
this.reqFavoriteSearch();
},
reqFavoriteSearch() {
this.loadingBox = true;
reqFavoriteSearch({
url_list: window.location.href,
publish_type: this.publish_type // 传递发布类型参数
}).then(res => {
this.loadingBox = false;
if (res.status) {
// 处理数据结构将product_info的子项提升到上一级
this.productList = this.flattenProductInfo(res.data.favorites);
} else {
this.$message.error(res.msg);
}
})
},
/**
* 将product_info的所有子项提升到products中每个产品的上一级去掉product_info字段
* @param {Array} historyList - 原始的历史记录列表
* @returns {Array} 处理后的历史记录列表
*/
flattenProductInfo(historyList) {
if (!Array.isArray(historyList)) {
return [];
}
return historyList.map(historyItem => {
if (historyItem.products && Array.isArray(historyItem.products)) {
// 处理每个历史记录中的products数组
const flattenedProducts = historyItem.products.map(product => {
if (product.product_info) {
// 将product_info的所有属性合并到product的上一级
const flattenedProduct = { ...product };
// 遍历product_info的所有属性
Object.keys(product.product_info).forEach(key => {
if(key == 'id'){
flattenedProduct.productid = product.product_info.id;
}
// 如果上一级已经有同名属性,则跳过(避免覆盖)
if (!(key in flattenedProduct)) {
flattenedProduct[key] = product.product_info[key];
}
});
// 删除product_info字段
delete flattenedProduct.product_info;
return flattenedProduct;
}
return product;
});
return {
...historyItem,
products: flattenedProducts
};
}
return historyItem;
});
},
/**
* 处理删除事件,从列表中移除被删除的项目
* @param {string} deletedId - 被删除项目的ID
*/
handleDeleteItem(deletedId) {
// 遍历productList找到包含被删除产品的历史记录
for (let i = 0; i < this.productList.length; i++) {
const historyItem = this.productList[i];
if (historyItem.products && Array.isArray(historyItem.products)) {
// 在products数组中查找并删除指定ID的产品
const productIndex = historyItem.products.findIndex(product => product.id === deletedId);
if (productIndex !== -1) {
// 删除该产品
historyItem.products.splice(productIndex, 1);
// 如果该历史记录下没有产品了,删除整个历史记录
if (historyItem.products.length === 0) {
this.productList.splice(i, 1);
}
// 更新视图
this.$forceUpdate();
break;
}
}
}
}
}
}
</script>
<style>
.followBox-title {
font-size: 32px;
font-weight: bold;
color: #363a46;
margin-bottom: 15px;
.hightText {
background: linear-gradient(90deg, #275aff, #2ebdfa);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
display: inline-block;
font-weight: 700;
}
}
.radio-group-container {
width: 100% !important;
display: flex;
justify-content: flex-start;
align-items: center;
max-width: 1400px;
}
.radio-group {
display: flex;
background: #fff;
border-radius: 8px;
margin-bottom: 15px;
}
.radio-item {
position: relative;
display: flex;
align-items: center;
justify-content: center;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
background: #fff;
border: 1px solid #e8e8e8;
margin-right: 4px;
font-size: 16px !important;
&:last-child {
margin-right: 0;
}
input[type="radio"] {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.radio-text {
font-size: 16px;
color: #275AFF;
font-weight: 500;
transition: all 0.3s ease;
}
&:hover {
border-color: #275AFF;
}
&.active {
background: linear-gradient(to right, #275AFF, #2EBDFA);
border-color: #275AFF;
box-shadow: 0 2px 8px rgba(39, 90, 255, 0.3);
.radio-text {
color: #fff;
}
}
}
/* 关注记录列表样式 */
.history-list {
margin-top: 20px;
}
.history-item {
background: #fff;
border-radius: 12px;
padding: 20px;
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
border: 1px solid #f0f0f0;
transition: all 0.3s ease;
}
.history-item:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
/* transform: translateY(-2px); */
}
.history-date {
display: flex;
align-items: center;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #f5f5f5;
}
.date-text {
font-size: 18px;
font-weight: 600;
color: #275AFF;
margin-right: 12px;
}
.relative-time {
font-size: 14px;
color: #999;
background: #f8f9fa;
padding: 4px 8px;
border-radius: 12px;
}
.history-content {
margin-top: 8px;
}
/* 空状态样式 */
.empty-state {
text-align: center;
padding: 60px 20px;
color: #999;
}
.empty-icon {
font-size: 48px;
margin-bottom: 16px;
opacity: 0.6;
}
.empty-text {
font-size: 16px;
color: #999;
}
</style>