wx-shop/pages/index/index.vue
2025-11-25 22:28:34 +08:00

725 lines
14 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>
<view class="header flex justify-between">
<view class="header-left">
<image class="icon" src="/static/images/home/icon-1.png"></image>
<text>香氛团购</text>
</view>
<view class="header-right flex">
<view>
<text class="iconfont icon-sousuo">
</text>
</view>
<view>
<text class="iconfont icon-aixin">
</text>
</view>
<view>
<text class="iconfont icon-zhifeiji1">
</text>
</view>
</view>
</view>
<view class="container">
<view class="search flex justify-between">
<view class="search-left flex">
<view class="recommend" :class="{ active: searchType == 1 }" @click="changeSearch(1)">
<text class="iconfont icon-tubiaoshangshengqushi"></text>
推荐产品
</view>
<view class="group-buying" :class="{ active: searchType == 2 }" @click="changeSearch(2)">
<text class="iconfont icon-aixin"></text>
拼团活动
</view>
</view>
<view class="search-right flex">
<view :class="{ active: searchType2 == 1 }" @click="changeSearch2(1)">
<text class="iconfont icon-wanggeshezhi">
</text>
</view>
<view :class="{ active: searchType2 == 2 }" @click="changeSearch2(2)">
<text class="iconfont icon-caidan">
</text>
</view>
<view :class="{ active: searchType2 == 3 }" @click="changeSearch2(3)">
<text class="iconfont icon-shaixuan1">
</text>
</view>
</view>
</view>
<view class="shop-list" v-if="searchType == 1">
<view class="shop-item" v-for="(item, index) in shopList" :key="item.id" @click="goShopDetail(item)">
<view class="shop-image">
<image :src="item.main_image_url" mode="aspectFit"></image>
<view class="shop-tag flex">
<view class="tag danger" v-if="item.is_hot_selling == 1">
<text class="iconfont icon-tubiaoshangshengqushi"></text>热销
</view>
<view class="tag warning">
-30%
</view>
</view>
</view>
<view class="shop-container">
<!-- <view class="shop-tags flex">
<view class="tag">
热销
</view>
<view class="tag">
热销
</view>
</view> -->
<view class="sku-title">
{{ item.name }}
</view>
<view class="sku-description">
{{ item.description.sub_title }}
</view>
<view class="sku-rating">
<text class="iconfont icon-xingxing"></text>
<text class="sku-rating-num">{{ item.rating }}</text>
<text class="sku-rating-text">156条评价 </text>
<text class="sku-rating-text"> {{ item.like_count }} 人喜欢</text>
</view>
<view class="sku-price" v-if="item.skus && item.skus.length > 0">
<text>{{ formatPrice(item.skus[0].price) }}</text>
<text class="original-price">{{ formatPrice(item.skus[0].original_price) }}</text>
</view>
<view class="sku-operation flex">
<view class="sku-num" @click.stop="handelLike(item)">
<text v-if="item.is_liked" class="iconfont icon-xin heart-filled"></text>
<text v-else class="iconfont icon-xin1 heart-outline"></text>
{{ item.like_count }}
</view>
<view class="">
<text class="iconfont icon-zhifeiji1"></text>
</view>
<view class="shop-cart">
<text class="iconfont icon-gouwuche"></text> 加入购物车
</view>
</view>
</view>
</view>
</view>
<view class="shop-list" v-if="searchType == 2">
<view class="shop-item">
<view class="shop-image">
<image src=""></image>
<view class="shop-tag flex">
<view class="tag danger">
<text class="iconfont icon-shandian"></text>拼团中
</view>
<view class="tag danger">
<text class="iconfont icon-tubiaoshangshengqushi"></text>热销
</view>
<view class="tag warning">
-30%
</view>
</view>
<view class="shop-tag flex buttom">
<view class="tag danger">
<text class="iconfont icon-shijian"></text>即将结束
</view>
</view>
</view>
<view class="shop-container">
<view class="sku-title">
3人拼团 玫瑰香水
</view>
<view class="sku-group-buying flex justify-between">
<view class="group-img">
</view>
<view class="">
<view class="group-name">
团长香香公主
</view>
<view class="group-text">
<text class="iconfont icon-yonghu"></text>还差1人成团
</view>
</view>
<view class="sku-group-rating">
<view class="group-rating">
<text class="iconfont icon-xingxing"></text>
<text class="sku-rating-num">4.6</text>
</view>
<view class="group-text">
信誉团长
</view>
</view>
</view>
<view class="sku-group-price flex justify-between">
<view class="group-price">
<view class="group-price-num">
<text>89</text>
<text class="original-price">129</text>
</view>
<view class="group-price-text">
拼团价
</view>
</view>
<view class="group-price-save">
<view class="save-tag">
<view>
<text class="iconfont icon-lihe"></text>
63
</view>
</view>
<view class="save-num">
立省30%
</view>
</view>
</view>
<view class="group-progress">
<view class="group-progress-num flex justify-between">
<text class="group-progress-text">拼团进度</text>
<text class="number">2/3 </text>
</view>
<view class="group-progress-width">
<progress :percent="50" stroke-width="20rpx" border-radius="20"
activeColor="#9810fa" />
</view>
<view class="group-progress-num font-text flex justify-between">
<text class="group-progress-text">已参团2人</text>
<text class="group-progress-text">还需1人</text>
</view>
</view>
<view class="sku-operation flex sku-operation2">
<view class="sku-num">
<text class="iconfont icon-aixin"></text> 423
</view>
<view class="">
<text class="iconfont icon-zhifeiji1"></text> 45
</view>
<view class="shop-cart">
<text class="iconfont icon-yonghu"></text> 立即参团
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import request from '/api/request';
import { parseDescription } from '/tools/format';
export default {
data() {
return {
searchType: 1,
searchType2: 2,
page: 1,
page_size: 10,
category_id: '',
name: '',
is_hot_selling: '',
is_limited: '',
shopList: '',
}
},
onLoad() {
this.getShopList()
},
methods: {
// 格式化价格
formatPrice(value) {
if (!value) {
return 0.00;
}
// 分转换为元
value = value / 100;
// 保留两位小数
return value.toFixed(2);
},
getShopList() {
request('xcx/products', 'get', {
page: this.page,
page_size: this.page_size
}).then((res) => {
this.shopList = res.list.map(item => {
item.description = parseDescription(item.description)
return item
})
console.log(this.shopList )
})
},
async userIsLogin() {
const token = await uni.getStorageSync('access_token')
if (token) {
return
} else {
uni.navigateTo({
url: '/pages/login/index'
})
}
},
changeSearch(index) {
this.searchType = index
},
changeSearch2(index) {
this.searchType2 = index
},
async handelLike(row) {
this.userIsLogin().then((res) => {
request('xcx/product/like', 'post', {
product_id: row.id,
type: row.is_liked ? 2 : 1
}).then((res) => {
const liked = !row.is_liked
row.is_liked = liked
if (liked) {
row.like_count += 1
} else if (row.like_count > 0) {
row.like_count -= 1
}
})
})
},
async goShopDetail(item) {
await uni.setStorageSync('product_info', item)
uni.navigateTo({
url: `/pages/shopDetail/index?id=${item.id}`
})
}
}
}
</script>
<style lang="scss" scoped>
.header {
padding: 30rpx;
box-shadow: 0 2rpx 6rpx 0 rgb(0 0 0 / 0.1), 0 2rpx 4rpx -2rpx rgb(0 0 0 / 0.1);
}
.header-left {
.icon {
width: 50rpx;
height: 50rpx;
vertical-align: middle;
margin-right: 20rpx;
}
text {
font-size: 30rpx;
color: #9810fa;
}
}
.header-right {
view {
box-shadow: none;
padding: 10rpx 10rpx;
height: 40rpx;
border: 0 solid transparent;
}
view+view {
margin-left: 20rpx;
}
}
.container {
padding: 40rpx 32rpx;
.search {
.search-left {
padding: 6rpx;
border-radius: 24rpx;
box-shadow: 0 2rpx 6rpx 0 rgb(0 0 0 / 0.1), 0 2rpx 4rpx -2rpx rgb(0 0 0 / 0.1);
view {
border-radius: 20rpx;
padding: 12rpx 12rpx;
font-size: 28rpx;
text {
margin: 0 6rpx;
}
}
.recommend {
image {
width: 40rpx;
height: 40rpx;
vertical-align: middle;
}
}
.group-buying {}
.active {
background-image: var(--background-linear-gradient);
color: #fff;
}
}
.search-right {
padding-top: 10rpx;
view {
width: 60rpx;
height: 60rpx;
border-radius: 20rpx;
line-height: 60rpx;
text-align: center;
font-size: 40rpx;
display: flex;
align-items: center;
justify-content: center;
}
view+view {
margin-left: 10rpx;
}
.active {
background-color: #f3e8ff;
color: #9810fa;
}
}
}
.shop-list {
margin-top: 60rpx;
.shop-item {
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
border-radius: 0 0 36rpx 36rpx;
image {
display: block;
width: 100%;
height: 400rpx;
}
.shop-container {
padding: 80rpx 32rpx;
.shop-tags {
.tag {
font-size: 20rpx;
color: #9810fa;
border: 2rpx solid #e9d4ff;
padding: 4rpx 10rpx;
border-radius: 12rpx;
}
.tag+.tag {
margin-left: 14rpx;
}
}
.sku-title {
margin-top: 20rpx;
font-size: 36rpx;
font-weight: bold;
}
.sku-description {
margin-top: 12rpx;
font-size: 28rpx;
color: #4a5565;
}
.sku-rating {
margin-top: 40rpx;
.iconfont {
font-size: 32rpx;
color: #f0b100;
margin-right: 20rpx;
}
.sku-rating-text {
font-size: 28rpx;
color: #4a5565;
}
}
.sku-price {
margin-top: 30rpx;
font-size: 48rpx;
color: #e7000b;
font-weight: bold;
.original-price {
margin-left: 20rpx;
font-size: 28rpx;
color: #99a1af;
font-weight: 400;
text-decoration: line-through;
}
}
.sku-operation {
margin-top: 40rpx;
justify-content: space-between;
view {
flex: 1;
border-radius: 12rpx;
text-align: center;
border: 2rpx solid rgb(0 0 0 / 0.1);
box-shadow: 0 2rpx 4rpx 0 rgb(0 0 0 / 0.05);
height: 60rpx;
line-height: 60rpx;
font-size: 24rpx;
}
.sku-num {
flex: 3;
margin-right: 30rpx;
.iconfont {
margin-right: 8rpx;
}
.heart-filled {
color: #e7000b;
// font-size: 28rpx;
}
.heart-outline {
color: #ccc;
// font-size: 24rpx;
// opacity: 0.8;
}
}
.shop-cart {
flex: 3;
margin-left: 30rpx;
// color: #fff;
background-image: var(--background-linear-gradient);
.iconfont {
margin-right: 8rpx;
}
}
}
.sku-operation2 {
view {
flex: auto;
border: 0;
box-shadow: none;
}
.sku-num {
flex: auto;
}
.shop-cart {
flex: auto;
background-image: none;
background-color: var(--color-danger);
color: #fff;
border-radius: 60rpx;
}
}
}
.shop-image {
position: relative;
image {
z-index: 0;
}
.shop-tag {
position: absolute;
top: 40rpx;
left: 32rpx;
z-index: 1;
.tag {
color: #fff;
height: 48rpx;
line-height: 48rpx;
font-size: 20rpx;
border-radius: 48rpx;
padding: 0 16rpx;
box-shadow: var(--tw-shadow);
text {
vertical-align: middle;
margin-right: 10rpx;
}
}
.tag+.tag {
margin-left: 14rpx;
}
.danger {
background-color: var(--color-danger);
}
.warning {
background-color: var(--color-warning);
}
.success {
background-color: var(--color-success);
}
}
.buttom {
top: auto;
buttom: 40rpx;
text {
font-size: 28rpx;
}
}
}
}
}
.sku-group-buying {
margin-top: 16rpx;
padding: 24rpx;
border-radius: 16rpx;
background-color: #fbf9fa;
.group-img {
width: 70rpx;
height: 70rpx;
border-radius: 70rpx;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
background-image: var(--background-linear-gradient);
}
.group-name {
font-weight: bold;
font-size: 28rpx;
}
.group-text {
margin-top: 4rpx;
font-size: 24rpx;
color: #6a7282;
text {
margin-right: 8rpx;
font-size: 28rpx;
}
}
.group-rating {
font-size: 28rpx;
color: #f0b100;
margin-right: 20rpx;
font-weight: bold;
text {
margin-right: 8rpx;
}
}
}
.sku-group-price {
margin-top: 32rpx;
padding: 24rpx;
border-radius: 16rpx;
background-color: #fff7ed;
.group-price-num {
font-size: 48rpx;
color: #e7000b;
font-weight: bold;
.original-price {
margin-left: 20rpx;
font-size: 28rpx;
color: #99a1af;
font-weight: 400;
text-decoration: line-through;
}
}
.group-price {
flex: 2;
}
.group-price-save {
flex: 1;
}
.group-price-text {
font-size: 24rpx;
color: #4a5565;
margin-left: 20rpx;
}
.save-tag {
// display: inline-block;
background-color: var(--color-danger);
color: #fff;
font-size: 24rpx;
.iconfont {
margin-right: 6rpx;
display: inline-block;
}
height: 48rpx;
line-height: 48rpx;
padding-left: 40rpx;
padding-right: 10rpx;
border-radius: 48rpx;
text-align: center;
}
.save-num {
margin-top: 16rpx;
font-size: 24rpx;
color: #4a5565;
text-align: right;
}
}
.group-progress {
margin-top: 32rpx;
font-size: 28rpx;
.group-progress-text {
font-size: 24rpx;
}
.number {
color: #9810fa;
font-weight: bold;
}
.group-progress-width {
margin-top: 26rpx;
margin-bottom: 26rpx;
}
.font-text {
color: #6a7282;
}
}
}
</style>