web-zk-h5/pages/shareArea/hiList.vue

691 lines
15 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>
<view class="contain">
<!-- Tab选项卡 -->
<view class="tab-container">
<view class="tab-wrapper">
<view
v-for="tab in tabs"
:key="tab.value"
class="tab-item"
:class="{ 'tab-active': activeTab === tab.value }"
@click="switchTab(tab.value)"
>
<text class="tab-text">{{ tab.label }}</text>
<view class="tab-line" v-if="activeTab === tab.value"></view>
</view>
</view>
</view>
<view class="goods-container">
<scroll-view
class="goodList"
scroll-y="true"
enhanced
:show-scrollbar="false"
>
<view v-for="item in goodList" :key="item.waresCode" class="goodList_i">
<img :src="item.cover1" class="cover" alt="" />
<view class="goodList_ir">
<view class="tit1">
{{ item.waresName }}
</view>
<view class="goodList_ib">
<view class="price-container">
<!-- <text class="currency">¥</text> -->
<text class="price">{{ formatCurrency(item.waresPrice) }}</text>
<text v-if="item.isSale === 1" class="sale-status">已售罄</text>
</view>
<!-- <img @click.stop="addCar(item)"
src="@/static/images/cart.png"
alt=""> -->
</view>
<!-- 数量控制区域 -->
<view class="quantity-section" v-if="item.isSale !== 1">
<view class="quantity-control">
<view
class="quantity-btn minus"
:class="{ disabled: item.quantity <= 1 }"
@click.stop="updateQuantity(item, -1)"
>
<text class="quantity-icon"></text>
</view>
<view class="quantity-display">
<text class="quantity-text">{{ item.quantity || 1 }}</text>
</view>
<view
class="quantity-btn plus"
@click.stop="updateQuantity(item, 1)"
>
<text class="quantity-icon">+</text>
</view>
</view>
<view class="toBuy" @click.stop="goBuy(item)">购买</view>
</view>
<!-- 禁售状态 -->
<view class="sold-out-section" v-if="item.isSale === 1">
<view class="sold-out-btn">暂时缺货</view>
</view>
</view>
</view>
<view class="list-bottom">
<text class="bottom-text"> 已显示全部商品 </text>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
import * as api from '@/config/login.js'
import { setToken } from '@/config/auth.js'
import { formatCurrency } from '@/util/index.js'
export default {
data() {
return {
pkParent: '',
goodList: [],
placeParent: '',
activeTab: 41, // 默认选中精品专区
tabs: [
{
label: '精品专区',
value: 41,
},
{
label: '商城专区',
value: 43,
},
],
}
},
onLoad(options) {
this.pkParent = options.pkParent
this.getToken()
},
methods: {
formatCurrency,
getToken() {
api
.autoLogin({
pkParent: this.pkParent,
})
.then(res => {
setToken(res.data.access_token, res.data.expires_in)
uni.setStorageSync('regiest-login', '1')
this.getList()
this.getCode()
})
},
getCode() {
api.fansConvertCode(this.pkParent).then(res => {
this.placeParent = res.data
uni.setStorageSync('placeParent', this.placeParent)
})
},
getList() {
api
.queryWares({
shareMemberCode: this.pkParent,
specialArea: this.activeTab,
})
.then(res => {
// 为每个商品初始化quantity字段
this.goodList = res.data.map(item => ({
...item,
quantity: item.quantity || 1,
}))
})
},
switchTab(value) {
if (this.activeTab !== value) {
this.activeTab = value
this.goodList = [] // 清空当前列表
this.getList() // 重新获取数据
}
},
updateQuantity(item, change) {
const newQuantity = (item.quantity || 1) + change
if (newQuantity >= 1) {
// 使用Vue.set或直接赋值来确保响应式更新
this.$set(item, 'quantity', newQuantity)
}
},
goBuy(item) {
const params = {
...item,
pkParent: this.pkParent,
specialArea: this.activeTab,
}
uni.navigateTo({
url: '/pages/shareArea/hiOrder?allData=' + JSON.stringify(item),
})
},
},
}
</script>
<style lang="scss" scoped>
.contain {
background: #f8fafc;
min-height: 100vh;
display: flex;
flex-direction: column;
}
// Tab选项卡样式
.tab-container {
background: #ffffff;
padding: 20rpx 24rpx 0;
position: relative;
z-index: 4;
.tab-wrapper {
display: flex;
justify-content: center;
position: relative;
.tab-item {
flex: none;
position: relative;
cursor: pointer;
margin: 0 32rpx;
padding: 16rpx 0;
.tab-text {
font-size: 30rpx;
font-weight: 500;
color: #9ca3af;
transition: all 0.3s ease;
}
.tab-line {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 3rpx;
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
border-radius: 2rpx;
animation: slideIn 0.3s ease;
}
&.tab-active {
.tab-text {
color: #1f2937;
font-weight: 600;
}
}
&:active {
.tab-text {
transform: scale(0.95);
}
}
}
}
}
// 商品容器区域
.goods-container {
flex: 1;
background: #f8fafc;
padding: 24rpx 24rpx 0;
position: relative;
z-index: 3;
.section-title {
text-align: center;
margin-bottom: 24rpx;
padding: 20rpx 0;
.title-text {
display: block;
color: #1e293b;
font-size: 32rpx;
font-weight: 600;
margin-bottom: 8rpx;
}
.title-desc {
display: block;
color: #64748b;
font-size: 24rpx;
}
}
}
// 商品列表滚动区域
.goodList {
height: calc(100vh - 400rpx);
padding: 0 8rpx;
.goodList_i {
display: flex;
background: #ffffff;
border-radius: 24rpx;
margin-bottom: 24rpx;
padding: 32rpx;
box-shadow: 0 4rpx 20rpx rgba(102, 126, 234, 0.08);
border: 1rpx solid rgba(102, 126, 234, 0.08);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
animation: slideInUp 0.6s ease-out both;
opacity: 0;
&:hover {
transform: translateY(-6rpx);
box-shadow: 0 16rpx 40rpx rgba(102, 126, 234, 0.2);
border-color: rgba(102, 126, 234, 0.15);
}
.cover {
width: 240rpx;
height: 240rpx;
background: #f8fafc;
border: 1rpx solid #e2e8f0;
border-radius: 16rpx;
flex-shrink: 0;
overflow: hidden;
}
.goodList_ir {
margin-left: 24rpx;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.tit1 {
color: #1e293b;
font-size: 32rpx;
font-weight: 600;
line-height: 1.4;
margin-bottom: 16rpx;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.sales {
color: #64748b;
font-size: 24rpx;
font-weight: 400;
margin-bottom: 16rpx;
}
.goodList_ib {
margin-bottom: 24rpx;
.price-container {
display: flex;
align-items: baseline;
justify-content: space-between;
.currency {
color: #ff6b35;
font-size: 24rpx;
font-weight: 600;
margin-right: 4rpx;
}
.price {
color: #ff6b35;
font-size: 36rpx;
font-weight: 700;
}
.sale-status {
color: #ef4444;
font-size: 24rpx;
font-weight: 500;
background: rgba(239, 68, 68, 0.1);
padding: 4rpx 12rpx;
border-radius: 12rpx;
border: 1rpx solid rgba(239, 68, 68, 0.2);
}
}
img {
width: 56rpx;
height: 56rpx;
}
}
// 数量控制区域
.quantity-section {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16rpx;
.quantity-control {
display: flex;
align-items: center;
background: #f8fafc;
border-radius: 20rpx;
border: 1rpx solid #e2e8f0;
overflow: hidden;
.quantity-btn {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
background: #ffffff;
transition: all 0.2s ease;
cursor: pointer;
.quantity-icon {
font-size: 32rpx;
font-weight: 600;
color: #667eea;
}
&.minus {
&.disabled {
opacity: 0.3;
cursor: not-allowed;
.quantity-icon {
color: #9ca3af;
}
}
}
&:not(.disabled):active {
background: #f1f5f9;
transform: scale(0.95);
}
}
.quantity-display {
min-width: 80rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
background: #ffffff;
border-left: 1rpx solid #e2e8f0;
border-right: 1rpx solid #e2e8f0;
.quantity-text {
font-size: 28rpx;
font-weight: 600;
color: #1f2937;
}
}
}
}
// 禁售状态区域
.sold-out-section {
display: flex;
justify-content: flex-end;
.sold-out-btn {
background: #f3f4f6;
color: #9ca3af;
padding: 16rpx 32rpx;
text-align: center;
border-radius: 12rpx;
font-size: 24rpx;
font-weight: 500;
border: 1rpx solid #e5e7eb;
cursor: not-allowed;
}
}
.toBuy {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
padding: 16rpx 24rpx;
text-align: center;
border-radius: 12rpx;
font-size: 24rpx;
font-weight: 600;
border: none;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
box-shadow: 0 2rpx 8rpx rgba(102, 126, 234, 0.2);
flex-shrink: 0;
min-width: 120rpx;
&::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.2),
transparent
);
transition: left 0.5s;
}
&:hover {
background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%);
transform: translateY(-1rpx);
box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.3);
&::before {
left: 100%;
}
}
&:active {
transform: scale(0.95) translateY(0);
}
}
}
}
.list-bottom {
text-align: center;
padding: 40rpx 0 60rpx;
.bottom-text {
color: #64748b;
font-size: 24rpx;
}
}
}
// 动画定义
@keyframes slideIn {
from {
transform: scaleX(0);
opacity: 0;
}
to {
transform: scaleX(1);
opacity: 1;
}
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-50rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideInUp {
from {
opacity: 0;
transform: translateY(40rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.02);
}
}
@keyframes promoBreathe {
0%,
100% {
transform: scale(1);
box-shadow: 0 8rpx 24rpx rgba(255, 107, 53, 0.4);
}
50% {
transform: scale(1.05);
box-shadow: 0 12rpx 32rpx rgba(255, 107, 53, 0.6);
}
}
@keyframes shimmer {
0% {
left: -100%;
}
50% {
left: -100%;
}
100% {
left: 100%;
}
}
// 商品卡片延迟动画
.goodList_i:nth-child(1) {
animation-delay: 0.1s;
}
.goodList_i:nth-child(2) {
animation-delay: 0.2s;
}
.goodList_i:nth-child(3) {
animation-delay: 0.3s;
}
.goodList_i:nth-child(4) {
animation-delay: 0.4s;
}
.goodList_i:nth-child(5) {
animation-delay: 0.5s;
}
.goodList_i:nth-child(n + 6) {
animation-delay: 0.6s;
}
// 响应式优化
@media (max-width: 750rpx) {
.tab-container {
padding: 24rpx 16rpx 0;
.tab-wrapper {
.tab-item {
margin: 0 24rpx;
padding: 12rpx 0;
.tab-text {
font-size: 28rpx;
}
}
}
}
.goodList {
.goodList_i {
padding: 24rpx;
.cover {
width: 200rpx;
height: 200rpx;
}
.goodList_ir {
margin-left: 20rpx;
.tit1 {
font-size: 28rpx;
}
.goodList_ib {
.price-container {
.price {
font-size: 32rpx;
}
}
}
.quantity-section {
.quantity-control {
.quantity-btn {
width: 50rpx;
height: 50rpx;
.quantity-icon {
font-size: 28rpx;
}
}
.quantity-display {
min-width: 70rpx;
height: 50rpx;
.quantity-text {
font-size: 24rpx;
}
}
}
}
.toBuy {
padding: 14rpx 20rpx;
font-size: 22rpx;
min-width: 100rpx;
}
.sold-out-section {
.sold-out-btn {
padding: 14rpx 28rpx;
font-size: 22rpx;
}
}
}
}
}
}
</style>