865 lines
22 KiB
Vue
865 lines
22 KiB
Vue
<template>
|
||
<view>
|
||
<!-- 比价和筛选按钮 -->
|
||
<view class="button-group">
|
||
<u-popup :show="popupShow" @close="close" @open="open" mode="bottom" round="10">
|
||
<view class="filter-popup">
|
||
<view class="filter-section">
|
||
<view class="section-title">出版社</view>
|
||
<view class="tag-group">
|
||
<u-tag v-for="(item, index) in publisherOptions" :key="index" v-if="item.visible"
|
||
:text="item.publisher" :plain="!item.checked" size="large" :name="index"
|
||
@click="togglePublisherFilter(index)" />
|
||
</view>
|
||
</view>
|
||
<view class="filter-section">
|
||
<view class="section-title">作者</view>
|
||
<view class="tag-group">
|
||
<u-tag v-for="(item, index) in authorOptions" :key="index" v-if="item.visible"
|
||
:text="item.author" :plain="!item.checked" size="large" :name="index"
|
||
@click="toggleAuthorFilter(index)" />
|
||
</view>
|
||
</view>
|
||
<view class="filter-buttons">
|
||
<u-button text="重置" type="info" plain @click="resetFilters" />
|
||
<u-button text="确定" type="primary" @click="applyFilters" />
|
||
</view>
|
||
</view>
|
||
</u-popup>
|
||
</view>
|
||
|
||
<view class="book-list">
|
||
<view class="product-header">
|
||
<view class="blue-block"></view>
|
||
<view class="title-text">
|
||
在售商品(总价/书价/运费)
|
||
</view>
|
||
<view class="header-buttons">
|
||
<view class="btn" :class="{ 'btn-loading': isLoading }" @click="switchCompareType"
|
||
v-if="showCompareButton">
|
||
<u-loading-icon v-if="isLoading" mode="circle" size="20" color="#ffffff"></u-loading-icon>
|
||
<text v-else>{{ compareType === 'isbn' ? '书名比价' : 'ISBN比价' }}</text>
|
||
</view>
|
||
<view class="btn" :class="{ 'btn-loading': isLoading }" @click="handleCopyrightCompare"
|
||
v-if="showCopyrightButton">
|
||
<u-loading-icon v-if="isLoading" mode="circle" size="20" color="#ffffff"></u-loading-icon>
|
||
<text v-else>版权页比价</text>
|
||
</view>
|
||
<view class="btn" @click="popupShow = true" v-if="showFilterButton">更多筛选</view>
|
||
</view>
|
||
</view>
|
||
<!-- 在售商品展示区域 -->
|
||
<view class="container" v-if="(isFiltered ? filteredOnSaleProducts : displayOnSaleProducts).length > 0">
|
||
<view class="product-grid">
|
||
<view class="product-card"
|
||
v-for="(product, index) in isFiltered ? filteredOnSaleProducts : displayOnSaleProducts"
|
||
:key="index">
|
||
<view class="product-image-container">
|
||
<image class="product-image" :src="product.imageUrl" mode="aspectFit"
|
||
@click="previewImage(product.imageUrl, isFiltered ? filteredOnSaleProducts : displayOnSaleProducts)">
|
||
</image>
|
||
<view class="price-details">
|
||
<text>{{product.totalPrice}}/{{product.bookPrice}}/{{product.shippingFee}}</text>
|
||
</view>
|
||
</view>
|
||
<view class="product-info">
|
||
<text class="product-price"
|
||
style="font-size: 26rpx;">{{product.totalPrice}}/{{product.qualityText}}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="empty-products" v-else>
|
||
<text>暂无在售商品信息</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { checkMemberBooksCount } from '@/components/MemberBookCheck.js';
|
||
|
||
export default {
|
||
name: 'BookProductList',
|
||
props: {
|
||
// 接收初始数据
|
||
initialOnSaleProducts: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
initialDisplayOnSaleProducts: {
|
||
type: Array,
|
||
default: () => []
|
||
},
|
||
initialCompareType: {
|
||
type: String,
|
||
default: 'isbn'
|
||
},
|
||
isbn: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
bookName: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
showCompareButton: {
|
||
type: Boolean,
|
||
default: true // 默认显示比价按钮
|
||
},
|
||
showCopyrightButton: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
publisher: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
author: {
|
||
type: String,
|
||
default: ''
|
||
},
|
||
showFilterButton: {
|
||
type: Boolean,
|
||
default: true
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
// 筛选相关
|
||
popupShow: false,
|
||
compareType: this.initialCompareType,
|
||
isLoading: false,
|
||
// 数据相关
|
||
onSaleProducts: this.initialOnSaleProducts,
|
||
displayOnSaleProducts: this.initialDisplayOnSaleProducts,
|
||
filteredOnSaleProducts: [],
|
||
// 筛选选项
|
||
publisherOptions: [],
|
||
authorOptions: [],
|
||
isFiltered: false,
|
||
// 关联映射
|
||
publisherAuthorMap: new Map(),
|
||
authorPublisherMap: new Map(),
|
||
// 添加排序类型
|
||
currentSortType: uni.getStorageSync('sortType') || '7', // 默认按总价排序
|
||
};
|
||
},
|
||
watch: {
|
||
initialOnSaleProducts: {
|
||
handler(newValue) {
|
||
this.onSaleProducts = newValue;
|
||
this.extractPublishersAndAuthors();
|
||
},
|
||
immediate: true
|
||
},
|
||
initialDisplayOnSaleProducts: {
|
||
handler(newValue) {
|
||
this.displayOnSaleProducts = newValue;
|
||
this.filteredOnSaleProducts = [...newValue];
|
||
},
|
||
immediate: true
|
||
},
|
||
initialCompareType: {
|
||
handler(newValue) {
|
||
this.compareType = newValue;
|
||
},
|
||
immediate: true
|
||
},
|
||
// 添加对排序类型的监听
|
||
currentSortType: {
|
||
handler(newSortType) {
|
||
if (this.onSaleProducts && this.onSaleProducts.length > 0) {
|
||
this.sortProducts(newSortType);
|
||
}
|
||
},
|
||
immediate: true
|
||
}
|
||
},
|
||
mounted() {
|
||
// 组件挂载时提取出版社和作者信息
|
||
this.extractPublishersAndAuthors();
|
||
},
|
||
methods: {
|
||
setCompareType(type) {
|
||
this.compareType = type;
|
||
},
|
||
// 打开和关闭筛选弹窗
|
||
open() {
|
||
this.popupShow = true;
|
||
},
|
||
close() {
|
||
this.popupShow = false;
|
||
},
|
||
|
||
// 切换比价类型
|
||
async switchCompareType() {
|
||
// 检查用户是否可以上传书籍
|
||
const canUpload = await checkMemberBooksCount();
|
||
if (!canUpload) {
|
||
// 如果不能上传,则直接返回,不继续执行
|
||
return;
|
||
}
|
||
// 如果正在加载中,直接返回
|
||
if (this.isLoading) return;
|
||
|
||
try {
|
||
// 设置加载状态
|
||
this.isLoading = true;
|
||
|
||
const newType = this.compareType === 'isbn' ? 'title' : 'isbn';
|
||
this.compareType = newType;
|
||
|
||
// 发出类型切换事件
|
||
await this.$emit('compare-type-change', {
|
||
type: newType,
|
||
value: newType === 'isbn' ? this.isbn : this.bookName
|
||
});
|
||
} catch (error) {
|
||
console.error('切换比价类型失败:', error);
|
||
|
||
// 检查是否是重复提交错误
|
||
if (error.responseData && error.responseData.code === 500 &&
|
||
error.responseData.msg === "Repeat submit is not allowed, please try again later") {
|
||
uni.showToast({
|
||
title: '操作太频繁,请稍后再试',
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
} else {
|
||
uni.showToast({
|
||
title: '切换失败,请稍后重试',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
} finally {
|
||
// 延迟关闭加载状态,避免闪烁
|
||
setTimeout(() => {
|
||
this.isLoading = false;
|
||
}, 500);
|
||
}
|
||
},
|
||
// 提取出版社和作者
|
||
extractPublishersAndAuthors() {
|
||
if (!this.onSaleProducts || this.onSaleProducts.length === 0) return;
|
||
|
||
// 创建出版社-作者关联映射
|
||
const publisherAuthorMap = new Map();
|
||
const authorPublisherMap = new Map();
|
||
|
||
// 遍历商品数据,建立关联关系
|
||
this.onSaleProducts.forEach(product => {
|
||
if (product.publisher && product.author) {
|
||
// 添加出版社-作者关联
|
||
if (!publisherAuthorMap.has(product.publisher)) {
|
||
publisherAuthorMap.set(product.publisher, new Set());
|
||
}
|
||
publisherAuthorMap.get(product.publisher).add(product.author);
|
||
|
||
// 添加作者-出版社关联
|
||
if (!authorPublisherMap.has(product.author)) {
|
||
authorPublisherMap.set(product.author, new Set());
|
||
}
|
||
authorPublisherMap.get(product.author).add(product.publisher);
|
||
}
|
||
});
|
||
|
||
// 保存关联映射
|
||
this.publisherAuthorMap = publisherAuthorMap;
|
||
this.authorPublisherMap = authorPublisherMap;
|
||
|
||
// 提取出版社
|
||
const publishers = new Set();
|
||
this.onSaleProducts.forEach(product => {
|
||
if (product.publisher) {
|
||
publishers.add(product.publisher);
|
||
}
|
||
});
|
||
|
||
// 提取作者
|
||
const authors = new Set();
|
||
this.onSaleProducts.forEach(product => {
|
||
if (product.author) {
|
||
authors.add(product.author);
|
||
}
|
||
});
|
||
|
||
// 转换为选项数组
|
||
this.publisherOptions = Array.from(publishers).map(publisher => ({
|
||
publisher,
|
||
checked: false,
|
||
visible: true
|
||
}));
|
||
|
||
this.authorOptions = Array.from(authors).map(author => ({
|
||
author,
|
||
checked: false,
|
||
visible: true
|
||
}));
|
||
},
|
||
|
||
// 切换出版社筛选
|
||
togglePublisherFilter(index) {
|
||
// 切换选中状态
|
||
this.publisherOptions[index].checked = !this.publisherOptions[index].checked;
|
||
|
||
// 获取所有选中的出版社
|
||
const selectedPublishers = this.publisherOptions
|
||
.filter(item => item.checked)
|
||
.map(item => item.publisher);
|
||
|
||
// 如果没有选中任何出版社,显示所有作者
|
||
if (selectedPublishers.length === 0) {
|
||
this.authorOptions.forEach(item => {
|
||
item.visible = true;
|
||
});
|
||
} else {
|
||
// 获取当前选中的出版社
|
||
const currentPublisher = this.publisherOptions[index].publisher;
|
||
|
||
// 如果取消选中,需要重新计算可见的作者
|
||
if (!this.publisherOptions[index].checked) {
|
||
// 重置所有作者的可见性
|
||
this.authorOptions.forEach(item => {
|
||
item.visible = false;
|
||
});
|
||
|
||
// 根据剩余选中的出版社更新作者可见性
|
||
selectedPublishers.forEach(publisher => {
|
||
if (this.publisherAuthorMap.has(publisher)) {
|
||
const relatedAuthors = this.publisherAuthorMap.get(publisher);
|
||
this.authorOptions.forEach(item => {
|
||
if (relatedAuthors.has(item.author)) {
|
||
item.visible = true;
|
||
}
|
||
});
|
||
}
|
||
});
|
||
} else {
|
||
// 如果是新选中,只显示与该出版社相关的作者
|
||
this.authorOptions.forEach(item => {
|
||
// 检查该作者是否与当前选中的出版社相关
|
||
if (this.publisherAuthorMap.has(currentPublisher)) {
|
||
const relatedAuthors = this.publisherAuthorMap.get(currentPublisher);
|
||
item.visible = relatedAuthors.has(item.author);
|
||
} else {
|
||
item.visible = false;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
// 取消选中不可见的作者
|
||
this.authorOptions.forEach(item => {
|
||
if (!item.visible) {
|
||
item.checked = false;
|
||
}
|
||
});
|
||
},
|
||
|
||
// 切换作者筛选
|
||
toggleAuthorFilter(index) {
|
||
// 切换选中状态
|
||
this.authorOptions[index].checked = !this.authorOptions[index].checked;
|
||
|
||
// 获取所有选中的作者
|
||
const selectedAuthors = this.authorOptions
|
||
.filter(item => item.checked)
|
||
.map(item => item.author);
|
||
|
||
// 如果没有选中任何作者,显示所有出版社
|
||
if (selectedAuthors.length === 0) {
|
||
this.publisherOptions.forEach(item => {
|
||
item.visible = true;
|
||
});
|
||
} else {
|
||
// 获取当前选中的作者
|
||
const currentAuthor = this.authorOptions[index].author;
|
||
|
||
// 如果取消选中,需要重新计算可见的出版社
|
||
if (!this.authorOptions[index].checked) {
|
||
// 重置所有出版社的可见性
|
||
this.publisherOptions.forEach(item => {
|
||
item.visible = false;
|
||
});
|
||
|
||
// 根据剩余选中的作者更新出版社可见性
|
||
selectedAuthors.forEach(author => {
|
||
if (this.authorPublisherMap.has(author)) {
|
||
const relatedPublishers = this.authorPublisherMap.get(author);
|
||
this.publisherOptions.forEach(item => {
|
||
if (relatedPublishers.has(item.publisher)) {
|
||
item.visible = true;
|
||
}
|
||
});
|
||
}
|
||
});
|
||
} else {
|
||
// 如果是新选中,只显示与该作者相关的出版社
|
||
this.publisherOptions.forEach(item => {
|
||
// 检查该出版社是否与当前选中的作者相关
|
||
if (this.authorPublisherMap.has(currentAuthor)) {
|
||
const relatedPublishers = this.authorPublisherMap.get(currentAuthor);
|
||
item.visible = relatedPublishers.has(item.publisher);
|
||
} else {
|
||
item.visible = false;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
// 取消选中不可见的出版社
|
||
this.publisherOptions.forEach(item => {
|
||
if (!item.visible) {
|
||
item.checked = false;
|
||
}
|
||
});
|
||
},
|
||
|
||
// 重置筛选
|
||
resetFilters() {
|
||
// 重置出版社选项
|
||
this.publisherOptions.forEach(item => {
|
||
item.checked = false;
|
||
item.visible = true;
|
||
});
|
||
|
||
// 重置作者选项
|
||
this.authorOptions.forEach(item => {
|
||
item.checked = false;
|
||
item.visible = true;
|
||
});
|
||
|
||
// 重置筛选状态
|
||
this.isFiltered = false;
|
||
|
||
// 恢复排序后的数据
|
||
this.filteredOnSaleProducts = [...this.displayOnSaleProducts];
|
||
|
||
// 关闭弹窗
|
||
this.popupShow = false;
|
||
|
||
// 发出重置事件
|
||
this.$emit('filters-reset');
|
||
},
|
||
|
||
// 应用筛选
|
||
applyFilters() {
|
||
// 获取选中的出版社
|
||
const selectedPublishers = this.publisherOptions
|
||
.filter(item => item.checked)
|
||
.map(item => item.publisher);
|
||
|
||
// 获取选中的作者
|
||
const selectedAuthors = this.authorOptions
|
||
.filter(item => item.checked)
|
||
.map(item => item.author);
|
||
|
||
// 如果没有选择任何筛选条件,则显示原始数据
|
||
if (selectedPublishers.length === 0 && selectedAuthors.length === 0) {
|
||
this.filteredOnSaleProducts = [...this.displayOnSaleProducts];
|
||
this.isFiltered = false;
|
||
} else {
|
||
// 筛选在售商品
|
||
let filteredProducts = this.onSaleProducts.filter(product => {
|
||
const matchPublisher = selectedPublishers.length === 0 ||
|
||
(product.publisher && selectedPublishers.includes(product.publisher));
|
||
const matchAuthor = selectedAuthors.length === 0 ||
|
||
(product.author && selectedAuthors.includes(product.author));
|
||
return matchPublisher && matchAuthor;
|
||
});
|
||
|
||
// 对筛选后的结果按总价从低到高排序
|
||
filteredProducts = filteredProducts.sort((a, b) => {
|
||
const priceA = parseFloat(a.totalPrice) || 0;
|
||
const priceB = parseFloat(b.totalPrice) || 0;
|
||
return priceA - priceB;
|
||
});
|
||
|
||
// 只保留前10条数据
|
||
this.filteredOnSaleProducts = filteredProducts.slice(0, 10);
|
||
this.isFiltered = true;
|
||
}
|
||
|
||
// 关闭弹窗
|
||
this.popupShow = false;
|
||
|
||
// 发出筛选结果事件
|
||
this.$emit('filters-applied', this.filteredOnSaleProducts);
|
||
},
|
||
|
||
// 预览图片
|
||
previewImage(currentUrl, productList) {
|
||
// 检查productList是否存在且是数组
|
||
let urls = [];
|
||
|
||
if (productList && Array.isArray(productList)) {
|
||
// 提取所有图片 URL
|
||
urls = productList.map(item => item.imageUrl);
|
||
} else {
|
||
// 如果productList不存在或不是数组,则只使用当前URL
|
||
urls = [currentUrl];
|
||
}
|
||
|
||
// 确保urls中至少有一个有效的URL
|
||
if (!urls.length || !urls[0]) {
|
||
console.error('没有有效的图片URL可预览');
|
||
return;
|
||
}
|
||
|
||
// 调用 UniApp 预览接口,添加长按操作
|
||
uni.previewImage({
|
||
current: currentUrl, // 当前显示图片
|
||
urls: urls, // 所有图片列表
|
||
longPressActions: {
|
||
itemList: ['保存图片', '分享图片'],
|
||
success: function(data) {
|
||
console.log('选择了第' + (data.tapIndex + 1) + '个按钮');
|
||
},
|
||
fail: function(err) {
|
||
console.log(err.errMsg);
|
||
}
|
||
},
|
||
success: () => {},
|
||
fail: (err) => {
|
||
console.error('预览失败:', err);
|
||
}
|
||
});
|
||
},
|
||
|
||
// 修改 updateProducts 方法
|
||
updateProducts(products) {
|
||
this.onSaleProducts = products;
|
||
this.sortProducts(this.currentSortType);
|
||
this.extractPublishersAndAuthors();
|
||
},
|
||
|
||
// 添加更新排序类型的方法
|
||
updateSortType(sortType) {
|
||
console.log('更新排序类型:', sortType);
|
||
this.currentSortType = sortType;
|
||
// 直接对现有数据进行排序
|
||
if (this.onSaleProducts && this.onSaleProducts.length > 0) {
|
||
this.sortProducts(sortType);
|
||
}
|
||
// 触发父组件重新获取数据
|
||
this.$emit('compare-type-change', {
|
||
type: this.compareType,
|
||
value: this.compareType === 'isbn' ? this.isbn : this.bookName,
|
||
sortType: sortType
|
||
});
|
||
},
|
||
|
||
// 修改 sortProducts 方法
|
||
sortProducts(sortType) {
|
||
console.log("123131231", sortType)
|
||
if (!this.onSaleProducts || this.onSaleProducts.length === 0) return;
|
||
|
||
// 根据排序方式选择排序字段
|
||
const sortField = sortType === '5' ? 'bookPrice' : 'totalPrice';
|
||
|
||
// 对商品数据按照选择的字段从低到高排序
|
||
const sortedData = [...this.onSaleProducts].sort((a, b) => {
|
||
const priceA = parseFloat(a[sortField]) || 0;
|
||
const priceB = parseFloat(b[sortField]) || 0;
|
||
return priceA - priceB;
|
||
});
|
||
|
||
// 只保留前12条数据用于展示
|
||
this.displayOnSaleProducts = sortedData.slice(0, 12);
|
||
this.filteredOnSaleProducts = [...this.displayOnSaleProducts];
|
||
this.isFiltered = false;
|
||
|
||
// 发出数据更新事件
|
||
this.$emit('products-updated', this.displayOnSaleProducts);
|
||
},
|
||
|
||
// 获取当前显示的商品数据
|
||
getCurrentProducts() {
|
||
return this.isFiltered ? this.filteredOnSaleProducts : this.displayOnSaleProducts;
|
||
},
|
||
|
||
// 获取筛选状态
|
||
getFilterStatus() {
|
||
return {
|
||
isFiltered: this.isFiltered,
|
||
selectedPublishers: this.publisherOptions.filter(item => item.checked).map(item => item.publisher),
|
||
selectedAuthors: this.authorOptions.filter(item => item.checked).map(item => item.author)
|
||
};
|
||
},
|
||
|
||
// 添加版权页比价方法
|
||
async handleCopyrightCompare() {
|
||
if (this.isLoading) return;
|
||
try {
|
||
this.isLoading = true;
|
||
// 打印传递参数日志
|
||
console.log('【版权页比价按钮参数】', {
|
||
bookName: this.bookName,
|
||
publisher: this.publisher,
|
||
author: this.author
|
||
});
|
||
// 发出版权页比价事件,传递出版社和作者信息
|
||
await this.$emit('copyright-compare', {
|
||
type: 'copyright',
|
||
bookName: this.bookName,
|
||
publisher: this.publisher,
|
||
author: this.author
|
||
});
|
||
} catch (error) {
|
||
console.error('版权页比价失败:', error);
|
||
uni.showToast({
|
||
title: '比价失败,请稍后重试',
|
||
icon: 'none'
|
||
});
|
||
} finally {
|
||
setTimeout(() => {
|
||
this.isLoading = false;
|
||
}, 500);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.book-list {
|
||
margin-top: 20rpx;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.book-list>.label {
|
||
padding: 10rpx;
|
||
display: block;
|
||
width: calc(100% - 20rpx);
|
||
height: 40rpx;
|
||
color: #333;
|
||
border-bottom: 2rpx solid #ccc;
|
||
}
|
||
|
||
.book-list>.label>.btn {
|
||
display: inline-block;
|
||
padding: 10rpx;
|
||
text-align: center;
|
||
width: 120rpx;
|
||
height: 30rpx;
|
||
line-height: 30rpx;
|
||
color: #fff;
|
||
background-color: #3c9cff;
|
||
border-radius: 10%;
|
||
margin-right: 10rpx;
|
||
}
|
||
|
||
.book-list>.container {
|
||
position: relative;
|
||
width: 100%;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.book-list>.container>.product-grid {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.book-list>.container>.product-grid>.product-card {
|
||
width: calc(25% - 8rpx);
|
||
background-color: #ffffff;
|
||
border-radius: 12rpx;
|
||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
||
overflow: hidden;
|
||
flex-shrink: 0;
|
||
height: 180rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
position: relative;
|
||
}
|
||
|
||
.book-list>.container>.product-grid>.product-card>.product-image-container {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 140rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.book-list>.container>.product-grid>.product-card>.product-image-container>.product-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: contain;
|
||
flex: 0 0 auto;
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.book-list>.container>.product-grid>.product-card>.product-image-container>.product-info {
|
||
padding: 8rpx;
|
||
font-size: 24rpx;
|
||
flex: 1;
|
||
overflow: hidden;
|
||
text-align: center;
|
||
}
|
||
|
||
.book-list>.container>.product-grid>.product-card>.product-image-container>.product-info>.product-price {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #ff6b00;
|
||
display: block;
|
||
margin-bottom: 4rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.book-list>.container>.product-grid>.product-card>.product-image-container>.price-details {
|
||
font-size: 22rpx;
|
||
line-height: 1.2;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: center;
|
||
gap: 8rpx;
|
||
color: #ffffff;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
padding: 4rpx 0;
|
||
border-radius: 0 0 8rpx 8rpx;
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 1;
|
||
}
|
||
|
||
.button-group {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
margin: 10rpx 0;
|
||
}
|
||
|
||
.filter-section {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.filter-popup {
|
||
padding: 30rpx;
|
||
background-color: #fff;
|
||
}
|
||
|
||
.filter-buttons {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-top: 40rpx;
|
||
}
|
||
|
||
.tag-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 10rpx;
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
.empty-products {
|
||
padding: 40rpx 0;
|
||
text-align: center;
|
||
color: #999;
|
||
font-size: 28rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
width: 100%;
|
||
}
|
||
|
||
/* 响应式布局 */
|
||
@media screen and (max-width: 768rpx) {
|
||
.book-list>.container>.product-grid>.product-card {
|
||
width: calc(25% - 7rpx);
|
||
}
|
||
}
|
||
|
||
@media screen and (max-width: 480rpx) {
|
||
.book-list>.container>.product-grid>.product-card {
|
||
width: calc(50% - 5rpx);
|
||
}
|
||
|
||
.book-list>.container>.product-grid>.product-card>.product-image-container {
|
||
height: 200rpx;
|
||
}
|
||
}
|
||
|
||
/* 新增商品列表标题栏样式 */
|
||
.product-header {
|
||
padding: 10rpx;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
width: calc(100% - 20rpx);
|
||
height: 40rpx;
|
||
color: #333;
|
||
border-bottom: 2rpx solid #ccc;
|
||
}
|
||
|
||
.title-text {
|
||
font-size: 28rpx;
|
||
flex: 1;
|
||
text-align: left;
|
||
}
|
||
|
||
.header-buttons {
|
||
display: flex;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.header-buttons .btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 6rpx 14rpx;
|
||
text-align: center;
|
||
width: 120rpx;
|
||
height: 30rpx;
|
||
line-height: 30rpx;
|
||
color: #fff;
|
||
background-color: #3c9cff;
|
||
border-radius: 10rpx;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.header-buttons .btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 6rpx 14rpx;
|
||
text-align: center;
|
||
width: 120rpx;
|
||
height: 30rpx;
|
||
line-height: 30rpx;
|
||
color: #fff;
|
||
background-color: #3c9cff;
|
||
border-radius: 10rpx;
|
||
font-size: 24rpx;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
/* 添加加载状态的样式 */
|
||
.btn-loading {
|
||
opacity: 0.7;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* 确保加载图标居中显示 */
|
||
.header-buttons .btn .u-loading-icon {
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.blue-block {
|
||
width: 8rpx;
|
||
height: 32rpx;
|
||
background-color: #007AFF;
|
||
margin-right: 16rpx;
|
||
border-radius: 4rpx;
|
||
}
|
||
</style> |