2025-11-26 15:42:54 +08:00

515 lines
12 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="historyBox">
<!-- 页面标题 -->
<div class="history-header">
<div class="historyBox-title">
<span>浏览</span>
<span class="hightText">记录</span>
</div>
<div class="history-subtitle">查看您的商品和需求浏览历史</div>
</div>
<!-- 筛选标签 -->
<div class="filter-section">
<div class="radio-group">
<label class="radio-item" :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 class="stats-info" v-if="productList.length > 0">
{{ getTotalItems() }} 条记录
</div>
</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">
<div class="date-content">
<span class="date-text">{{ formatBrowseDate(item.browse_date) }}</span>
<span class="relative-time">{{ getRelativeTime(item.browse_date) }}</span>
</div>
</div>
<div class="history-content">
<productCard
contentType="history"
: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-content">
<div class="empty-icon">📋</div>
<div class="empty-text">暂无浏览记录</div>
<div class="empty-desc">您还没有浏览过任何{{ publish_type === '1' ? '商品' : '需求' }}快去探索吧</div>
<div class="empty-action">
<el-button
type="primary"
@click="$router.push('/ncmatchHome')"
class="explore-btn">
去首页逛逛
</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import { reqUserBrowseHistorySearch } from '@/api/ncmatch';
import productCard from '../mainPage/productCard/index.vue';
import { formatBrowseDate, getRelativeTime } from './tool.js';
export default {
name: 'historyBox',
data() {
return {
loadingBox: false,
productList: [],
publish_type: '1', // 默认选择企业商品
}
},
created() {
this.reqUserBrowseHistorySearch();
},
components: {
productCard
},
methods: {
formatBrowseDate,
getRelativeTime,
handleTypeChange() {
// 当类型改变时重新获取数据
this.reqUserBrowseHistorySearch();
},
reqUserBrowseHistorySearch() {
this.loadingBox = true;
reqUserBrowseHistorySearch({
url_list: window.location.href,
publish_type: this.publish_type
}).then(res => {
this.loadingBox = false;
if (res.status) {
this.productList = this.flattenProductInfo(res.data.history_list);
} else {
this.$message.error(res.msg || '获取浏览记录失败');
}
}).catch(error => {
this.loadingBox = false;
this.$message.error('网络错误,请稍后重试');
console.error('获取浏览记录失败:', error);
});
},
/**
* 将product_info的所有子项提升到products中每个产品的上一级去掉product_info字段
*/
flattenProductInfo(historyList) {
if (!Array.isArray(historyList)) {
return [];
}
return historyList.map(historyItem => {
if (historyItem.products && Array.isArray(historyItem.products)) {
const flattenedProducts = historyItem.products.map(product => {
if (product.product_info) {
const flattenedProduct = { ...product };
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];
}
});
delete flattenedProduct.product_info;
return flattenedProduct;
}
return product;
});
return {
...historyItem,
products: flattenedProducts
};
}
return historyItem;
});
},
/**
* 处理删除事件,从列表中移除被删除的项目
*/
handleDeleteItem(deletedId) {
for (let i = 0; i < this.productList.length; i++) {
const historyItem = this.productList[i];
if (historyItem.products && Array.isArray(historyItem.products)) {
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();
this.$message.success('删除成功');
break;
}
}
}
},
/**
* 获取总记录数
*/
getTotalItems() {
return this.productList.reduce((total, item) => {
return total + (item.products ? item.products.length : 0);
}, 0);
}
}
}
</script>
<style scoped>
.historyBox {
max-width: 1400px;
margin: 0 auto;
padding: 30px 20px;
min-height: calc(100vh - 100px);
}
/* 页面标题区域 */
.history-header {
text-align: center;
margin-bottom: 40px;
padding: 0 20px;
}
.historyBox-title {
font-size: 36px;
font-weight: bold;
color: #363a46;
margin-bottom: 12px;
line-height: 1.2;
}
.historyBox-title .hightText {
background: linear-gradient(135deg, #275aff, #2ebdfa);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-weight: 700;
}
.history-subtitle {
font-size: 16px;
color: #666;
opacity: 0.8;
}
/* 筛选区域 */
.filter-section {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding: 0 20px;
flex-wrap: wrap;
gap: 20px;
}
.radio-group {
display: flex;
background: #fff;
border-radius: 12px;
padding: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
border: 1px solid #f0f0f0;
}
.radio-item {
position: relative;
display: flex;
align-items: center;
justify-content: center;
padding: 12px 24px;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
background: transparent;
font-size: 14px;
}
.radio-item:last-child {
margin-right: 0;
}
.radio-item input[type="radio"] {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.radio-text {
font-size: 14px;
color: #666;
font-weight: 500;
transition: all 0.3s ease;
}
.radio-item:hover {
background: rgba(39, 90, 255, 0.05);
}
.radio-item.active {
background: linear-gradient(135deg, #275AFF, #2EBDFA);
box-shadow: 0 4px 12px rgba(39, 90, 255, 0.3);
}
.radio-item.active .radio-text {
color: #fff;
font-weight: 600;
}
.stats-info {
font-size: 14px;
color: #666;
background: #f8f9fa;
padding: 8px 16px;
border-radius: 20px;
font-weight: 500;
}
/* 历史记录列表样式 */
.history-list {
margin-top: 20px;
}
.history-item {
background: #fff;
border-radius: 16px;
padding: 24px;
margin-bottom: 20px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
border: 1px solid #f0f0f0;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.history-item::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 4px;
background: linear-gradient(to bottom, #275AFF, #2EBDFA);
opacity: 0;
transition: opacity 0.3s ease;
}
.history-item:hover {
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
.history-item:hover::before {
opacity: 1;
}
.history-date {
margin-bottom: 20px;
padding-bottom: 16px;
border-bottom: 1px solid #f5f5f5;
}
.date-content {
display: flex;
align-items: center;
gap: 12px;
}
.date-icon {
font-size: 18px;
}
.date-text {
font-size: 18px;
font-weight: 600;
color: #275AFF;
}
.relative-time {
font-size: 14px;
color: #999;
background: #f8f9fa;
padding: 6px 12px;
border-radius: 16px;
font-weight: 500;
}
.history-content {
margin-top: 8px;
}
/* 空状态样式 */
.empty-state {
text-align: center;
padding: 80px 20px;
margin-top: 40px;
}
.empty-content {
max-width: 400px;
margin: 0 auto;
}
.empty-icon {
font-size: 80px;
margin-bottom: 24px;
opacity: 0.6;
}
.empty-text {
font-size: 20px;
color: #333;
margin-bottom: 12px;
font-weight: 600;
}
.empty-desc {
font-size: 14px;
color: #999;
margin-bottom: 30px;
line-height: 1.6;
}
.explore-btn {
padding: 12px 32px;
border-radius: 8px;
font-weight: 500;
background: linear-gradient(135deg, #275AFF, #2EBDFA);
border: none;
transition: all 0.3s ease;
}
.explore-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(39, 90, 255, 0.3);
}
/* 响应式设计 */
@media (max-width: 768px) {
.historyBox {
padding: 20px 15px;
}
.history-header {
margin-bottom: 30px;
}
.historyBox-title {
font-size: 28px;
}
.filter-section {
flex-direction: column;
align-items: stretch;
gap: 15px;
}
.radio-group {
width: 100%;
justify-content: center;
}
.radio-item {
flex: 1;
padding: 10px 16px;
}
.stats-info {
align-self: center;
}
.history-item {
padding: 20px;
border-radius: 12px;
}
.date-content {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
.empty-state {
padding: 60px 15px;
}
.empty-icon {
font-size: 60px;
}
.empty-text {
font-size: 18px;
}
}
@media (max-width: 480px) {
.historyBox {
padding: 15px 10px;
}
.historyBox-title {
font-size: 24px;
}
.history-item {
padding: 16px;
margin-bottom: 16px;
}
.date-text {
font-size: 16px;
}
.radio-item {
padding: 8px 12px;
}
.empty-icon {
font-size: 50px;
}
}
/* 加载状态优化 */
::v-deep .el-loading-mask {
border-radius: 16px;
}
::v-deep .el-loading-spinner .circular {
width: 42px;
height: 42px;
}
::v-deep .el-loading-spinner .path {
stroke: #275AFF;
}
</style>