11 changed files with 503 additions and 36 deletions
-
6src/pages.json
-
2src/subpackage/mall/components/index_classify_bar.vue
-
13src/subpackage/mall/components/index_search_bar.vue
-
2src/subpackage/mall/components/specification_modal.vue
-
2src/subpackage/mall/js/api.js
-
25src/subpackage/mall/js/handle.js
-
441src/subpackage/mall/pages/classify.vue
-
34src/subpackage/mall/pages/goods_info.vue
-
12src/subpackage/mall/pages/index.vue
-
BINsrc/subpackage/mall/static/images/arrow_094.png
-
BINsrc/subpackage/mall/static/images/arrow_9ad_down.png
@ -0,0 +1,25 @@ |
|||||
|
import { MALL_API } from "./api"; |
||||
|
import server from "./server"; |
||||
|
|
||||
|
// 购物车商品列表
|
||||
|
export function goodsCartList(brand_id){ |
||||
|
return server.post({ |
||||
|
url: MALL_API.goodsCartList, |
||||
|
data: { brand_id }, |
||||
|
isDefaultGet: false, |
||||
|
}) |
||||
|
.then(res => { |
||||
|
let _data = res?.data || {}; |
||||
|
if(_data.code === 0){ |
||||
|
let _ls = _data?.data ?? []; |
||||
|
//product_invalid 商品状态 0-正常 1-已失效
|
||||
|
return ({ |
||||
|
totalList: _ls, |
||||
|
validList: _ls.filter(item => item.product_invalid === 0), |
||||
|
invalidList: _ls.filter(item => item.product_invalid === 0), |
||||
|
}); |
||||
|
}else{ |
||||
|
return Promise.reject(_data); |
||||
|
} |
||||
|
}) |
||||
|
} |
@ -0,0 +1,441 @@ |
|||||
|
<template> |
||||
|
<view class="mall-classify"> |
||||
|
<view class="mc-search-bar"> |
||||
|
<index-search-bar shopping-cart :cart-num="goodsCartNum"></index-search-bar> |
||||
|
</view> |
||||
|
<view class="mc-section"> |
||||
|
<scroll-view class="ms-classify" :style="scrollStyle" scroll-y> |
||||
|
<view class="mc-box"> |
||||
|
<view :class="['mc-item','defaultOne', curTab == -1 ? 'activeOne' : '',curTab==0?'filletOne':'']" @click="likeChange()">❤️猜你喜欢</view> |
||||
|
<view |
||||
|
v-for="(e, i) in goodsCateList" |
||||
|
:key="i" |
||||
|
:class="['mc-item', curTab == i ? 'active' : '',curTab == (i + 1)?'filletUnder':'', curTab == (i - 1)?'filletOn':'']" |
||||
|
@click="tabChange(e,i)" |
||||
|
> |
||||
|
{{ e.product_cate_name || '-' }} |
||||
|
</view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
<scroll-view class="ms-goods" :style="scrollStyle" scroll-y scroll-with-animation> |
||||
|
<!-- 除猜你喜欢外显示 --> |
||||
|
<view class="mg-tab" v-if="curTab != -1"> |
||||
|
<view v-for="(e, i) in goodsKeyList" :key="i" :class="['mt-item', curItemTab == e.id ? 'active' : '']" @click="tabItemChange(e)"> |
||||
|
{{ e.name }} |
||||
|
<view v-if="curItemTab == i && curItemTab!=0"> |
||||
|
<image |
||||
|
:src="isSort ? '/subpackage/mall/static/images/arrow_9ad_down.png' : '/subpackage/mall/static/images/arrow_094.png'" |
||||
|
:style="isSort ? 'transform: rotateZ(180deg)' : ''" |
||||
|
></image> |
||||
|
<image |
||||
|
:src="isSort ? '/subpackage/mall/static/images/arrow_094.png' : '/subpackage/mall/static/images/arrow_9ad_down.png'" |
||||
|
:style="isSort ? 'transform: rotateZ(180deg)' : ''" |
||||
|
></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="mg-list"> |
||||
|
<view class="ml-item" v-for="(e, i) in goodsList" :key="i" @click="goodsItemChange(e.id)"> |
||||
|
<image mode="aspectFill" :src="e.product_imgs[0] || ''"></image> |
||||
|
<view> |
||||
|
<view>{{e.product_name || ''}}</view> |
||||
|
<view>{{e.product_text || ''}}</view> |
||||
|
<!-- 特价标签 现在不做 --> |
||||
|
<!-- <view class="mi-tags"> |
||||
|
<view class="mt-b">特价</view> |
||||
|
</view> --> |
||||
|
<view class="mi-price"> |
||||
|
<view class="mp-price"> |
||||
|
<text>¥</text> |
||||
|
<text>{{e.product_price || 0}}</text> |
||||
|
<!-- 单位: /2支 现在不做 --> |
||||
|
<text>{{''}}</text> |
||||
|
<text v-if="e.product_spec_multi == 0 && e.product_price_show != 0">¥{{e.product_price_show || 0}}</text> |
||||
|
</view> |
||||
|
<view class="mp-btn" @click.stop="addGoodsChange(e)"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="mg-tip">我是有底线的~</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
<!-- 分类 --> |
||||
|
<spacification-modal ref="spacificationModal" button-txt="加入购物车"></spacification-modal> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import { routeTo, showLoad, hideLoad, showModal, getNodeMes } from "@/utils/util.js"; |
||||
|
import { MALL_API } from "../js/api"; |
||||
|
import server from "../js/server"; |
||||
|
import { goodsCartList } from "../js/handle"; |
||||
|
import spacificationModal from "../components/specification_modal.vue"; |
||||
|
import indexSearchBar from "../components/index_search_bar.vue"; |
||||
|
export default { |
||||
|
components: { spacificationModal, indexSearchBar }, |
||||
|
computed: { |
||||
|
scrollStyle() { |
||||
|
let { scrollHeight } = this; |
||||
|
return `height: ${scrollHeight}px;`; |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
scrollHeight: 658, // 658 为ipx的高度 |
||||
|
brand_id: '', |
||||
|
curTab: -1, //当前选中的商品分类列表id, 默认固定-1为猜你喜欢 |
||||
|
curItemTab: 0, |
||||
|
isSort: true, |
||||
|
goodsKeyList: [{id: 0, name: '综合'},{id: 1, name: '销量'},{id: 2, name: '价格'}], |
||||
|
goodsCateList: [], //商品分类列表 |
||||
|
goodsList: [], //商品列表 |
||||
|
goodsCartNum: 0, // 购物车数量 |
||||
|
cateId: -1, |
||||
|
|
||||
|
}; |
||||
|
}, |
||||
|
async onLoad(opts) { |
||||
|
let _bid = opts?.brand_id ?? ''; |
||||
|
this.brand_id = _bid |
||||
|
this.setScrollHeight(); |
||||
|
this.getCateList(_bid); |
||||
|
this.getGoodsList({ brand_id: _bid, recommend: 1 }); |
||||
|
}, |
||||
|
async onShow() { |
||||
|
let { brand_id } = this; |
||||
|
this.getCartList(brand_id); |
||||
|
}, |
||||
|
methods: { |
||||
|
async setScrollHeight() { |
||||
|
let searchBar = await getNodeMes('.mc-search-bar'); |
||||
|
let sysInfo = uni.getWindowInfo(); |
||||
|
this.scrollHeight = (sysInfo.windowHeight - searchBar.height) || 658; // 658 为ipx的高度 |
||||
|
}, |
||||
|
// 商品分类列表 |
||||
|
tabChange(e,i) { |
||||
|
let { brand_id } = this; |
||||
|
this.isSort = true |
||||
|
this.curTab = i; |
||||
|
this.cateId = e.id |
||||
|
this.getGoodsList({ brand_id, cateid: e.id }); |
||||
|
}, |
||||
|
// 猜你喜欢 |
||||
|
likeChange(){ |
||||
|
let { brand_id } = this; |
||||
|
this.curTab = -1; |
||||
|
this.getGoodsList({ brand_id, recommend: 1 }); |
||||
|
}, |
||||
|
// 综合 销量 价格 |
||||
|
tabItemChange(e) { |
||||
|
let { brand_id } = this; |
||||
|
this.curItemTab = e.id; |
||||
|
this.isSort = !this.isSort; |
||||
|
let sort = ''; |
||||
|
if(e.id == 1 && !this.isSort) sort = 'product_sale_nums|desc'; //销量从高到低 |
||||
|
if(e.id == 1 && this.isSort) sort = 'product_sale_nums|asc'; //销量从低到高 |
||||
|
if(e.id == 2 && !this.isSort) sort = 'product_price|desc'; //价格从高到低 |
||||
|
if(e.id == 2 && this.isSort) sort = 'product_price|asc'; //价格从低到高 |
||||
|
|
||||
|
this.$nextTick(_=>{ |
||||
|
this.getGoodsList({ |
||||
|
brand_id, |
||||
|
cateid: this.cateId, |
||||
|
show_sort: sort, |
||||
|
}); |
||||
|
}) |
||||
|
|
||||
|
}, |
||||
|
goodsItemChange(id) { |
||||
|
let { brand_id } = this; |
||||
|
routeTo(`/subpackage/mall/pages/goods_info?id=${id}&brand_id=${brand_id}`,'nT') |
||||
|
}, |
||||
|
async addGoodsChange(e) { |
||||
|
let { brand_id } = this; |
||||
|
// 如果商品是多个规格属性的,则出现弹窗给用户选择规格加入购物车,如果是单规格的则直接加入购物车 |
||||
|
// 根据product_spec_multi字段做判断 等于1则是多规格 |
||||
|
if(e.product_spec_multi == 1){ |
||||
|
return this.$refs.spacificationModal.alert({ |
||||
|
id: e?.id ?? '', |
||||
|
brand_id: brand_id, |
||||
|
poster: e?.product_imgs?.[0] ?? '', |
||||
|
name: e?.product_name ?? '', |
||||
|
price: e?.product_price ?? '', |
||||
|
specArr: e?.product_spec ?? [], |
||||
|
addCartComplete: res => { |
||||
|
this.getCartList(brand_id); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
// 单规格 |
||||
|
await this.$refs?.spacificationModal?.goodsCartAdd({ brand_id, id: e?.id, }); |
||||
|
this.getCartList(brand_id); |
||||
|
}, |
||||
|
// 商品分类列表 |
||||
|
getCateList(brand_id) { |
||||
|
showLoad(); |
||||
|
return server.post({ |
||||
|
url: MALL_API.goodsCateList, |
||||
|
data: { brand_id}, |
||||
|
isDefaultGet: false, |
||||
|
}) |
||||
|
.then(res => { |
||||
|
hideLoad(); |
||||
|
let _data = res?.data || {}; |
||||
|
if(_data.code === 0){ |
||||
|
return this.goodsCateList = _data?.data ?? []; |
||||
|
}else{ |
||||
|
return Promise.reject(_data); |
||||
|
} |
||||
|
}) |
||||
|
.catch(err => { |
||||
|
hideLoad(); |
||||
|
showModal({ content: err.message || '加载失败!' }); |
||||
|
console.warn('subpackage mall pages classify getCateList err --->', err); |
||||
|
}) |
||||
|
}, |
||||
|
// 商品列表 ps:猜你喜欢分类,recommend固定为1,分类ID传空; 其他分类又分 综合 销量 价格 |
||||
|
getGoodsList({brand_id, cateid='', show_sort='', recommend='', page = 1, page_size = 20}){ |
||||
|
// show_sort: 排序,eg:价格高到低(product_price|desc),销量低到高(product_sale_nums|asc) |
||||
|
// product_price这个表示价格的字段 product_sale_nums这个表示销量的字段 desc这个表示排序方法(desc是倒序asc是正序) |
||||
|
// show_sort等于空或者不传就是综合的 |
||||
|
let _query = { brand_id, cateid, show_sort, recommend, page, page_size }; |
||||
|
showLoad(); |
||||
|
return server.post({ |
||||
|
url: MALL_API.goodsList, |
||||
|
data: _query, |
||||
|
isDefaultGet: false, |
||||
|
}) |
||||
|
.then(res => { |
||||
|
hideLoad(); |
||||
|
let _data = res?.data || {}; |
||||
|
if(_data.code === 0){ |
||||
|
return this.goodsList = _data?.data?.list ?? []; |
||||
|
}else{ |
||||
|
return Promise.reject(_data); |
||||
|
} |
||||
|
}) |
||||
|
.catch(err => { |
||||
|
hideLoad(); |
||||
|
showModal({ content: err.message || '加载失败!' }); |
||||
|
console.warn('subpackage mall pages classify getGoodsList err --->', err); |
||||
|
}) |
||||
|
}, |
||||
|
|
||||
|
// 购物车-商品列表 |
||||
|
async getCartList(brand_id) { |
||||
|
try{ |
||||
|
let { validList } = await goodsCartList(brand_id); |
||||
|
let _length = validList?.length ?? 0; |
||||
|
this.goodsCartNum = _length > 100 ? 99 : _length; |
||||
|
}catch(err){ |
||||
|
console.warn('subpackage mall pages classify getCartList err --->', err); |
||||
|
} |
||||
|
}, |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"> |
||||
|
.mall-classify { |
||||
|
.mc-section { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
.ms-classify { |
||||
|
flex-shrink: 0; |
||||
|
flex-grow: 0; |
||||
|
width: 180upx; |
||||
|
background-color: #ededf5; |
||||
|
.mc-box{ |
||||
|
background-color: #fff; |
||||
|
} |
||||
|
.mc-item { |
||||
|
padding: 0 10upx; |
||||
|
height: 92upx; |
||||
|
line-height: 92upx; |
||||
|
text-align: center; |
||||
|
font-size: 28upx; |
||||
|
color: #9a9a9d; |
||||
|
background-color: #ededf5; |
||||
|
@include tHide(1); |
||||
|
} |
||||
|
.active { |
||||
|
font-weight: 500; |
||||
|
background-color: #fff; |
||||
|
} |
||||
|
.filletOn{ |
||||
|
border-top-right-radius: 10rpx; |
||||
|
} |
||||
|
.filletUnder{ |
||||
|
border-bottom-right-radius: 10rpx; |
||||
|
} |
||||
|
.filletOne{ |
||||
|
border-bottom-right-radius: 10rpx; |
||||
|
} |
||||
|
.defaultOne { |
||||
|
color: #333; |
||||
|
} |
||||
|
.activeOne { |
||||
|
color: $mColor; |
||||
|
background-color: #fff; |
||||
|
} |
||||
|
} |
||||
|
.ms-goods { |
||||
|
// width: 570upx; |
||||
|
flex-grow: 1; |
||||
|
.mg-tab { |
||||
|
flex-grow: 1; |
||||
|
width: 100%; |
||||
|
height: 92rpx; |
||||
|
padding: 0rpx 40rpx; |
||||
|
background-color: #fbfbff; |
||||
|
@include ctf(space-between); |
||||
|
//吸顶 |
||||
|
/* #ifndef APP-PLUS-NVUE */ |
||||
|
display: flex; |
||||
|
position: -webkit-sticky; |
||||
|
/* #endif */ |
||||
|
position: sticky; |
||||
|
top: var(--window-top); |
||||
|
z-index: 6; |
||||
|
.mt-item { |
||||
|
color: #9a9a9d; |
||||
|
font-size: 24rpx; |
||||
|
min-width: 80rpx; |
||||
|
@include ctf(flex-start); |
||||
|
> view { |
||||
|
margin-left: 10rpx; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
> image { |
||||
|
flex-shrink: 0; |
||||
|
width: 12rpx; |
||||
|
height: 12rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.active { |
||||
|
color: $mColor; |
||||
|
} |
||||
|
} |
||||
|
.mg-list { |
||||
|
padding: 20upx 20upx 30upx; |
||||
|
background-color: #fff; |
||||
|
.ml-item { |
||||
|
padding-bottom: 28upx; |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
> image { |
||||
|
flex-shrink: 0; |
||||
|
margin-right: 20upx; |
||||
|
width: 172upx; |
||||
|
height: 172upx; |
||||
|
} |
||||
|
> view { |
||||
|
flex-grow: 1; |
||||
|
background-color: #fff; |
||||
|
> view:first-child { |
||||
|
margin-bottom: 10upx; |
||||
|
font-size: 28upx; |
||||
|
line-height: 40upx; |
||||
|
@include tHide(2); |
||||
|
} |
||||
|
> view:nth-child(2) { |
||||
|
margin-bottom: 14upx; |
||||
|
line-height: 32upx; |
||||
|
min-height: 32rpx; |
||||
|
font-size: 22upx; |
||||
|
color: #9a9a9d; |
||||
|
@include tHide(1); |
||||
|
} |
||||
|
.mi-tags { |
||||
|
margin-bottom: 10upx; |
||||
|
@include ctf(flex-start); |
||||
|
.mt-a { |
||||
|
margin-right: 10upx; |
||||
|
padding: 0 6upx; |
||||
|
border-radius: 6upx; |
||||
|
line-height: 28upx; |
||||
|
font-size: 20upx; |
||||
|
color: #ff873d; |
||||
|
background: rgba(246, 132, 62, 0.28); |
||||
|
} |
||||
|
.mt-b { |
||||
|
padding: 0 8upx; |
||||
|
font-size: 20upx; |
||||
|
line-height: 28upx; |
||||
|
border-radius: 8upx; |
||||
|
color: #e60012; |
||||
|
border: 2upx solid rgba($color: #e60213, $alpha: 0.5); |
||||
|
// background: rgba(230, 0, 18, 0.13); |
||||
|
} |
||||
|
} |
||||
|
.mi-price { |
||||
|
@include ctf(space-between); |
||||
|
.mp-price { |
||||
|
flex-grow: 1; |
||||
|
@include tHide(1); |
||||
|
line-height: 40upx; |
||||
|
color: #ff873d; |
||||
|
> text { |
||||
|
&:first-child { |
||||
|
font-size: 28upx; |
||||
|
} |
||||
|
&:nth-child(2) { |
||||
|
font-size: 36upx; |
||||
|
} |
||||
|
&:nth-child(3) { |
||||
|
font-size: 26upx; |
||||
|
color: #333; |
||||
|
} |
||||
|
&:nth-child(4) { |
||||
|
font-size: 26upx; |
||||
|
color: #9a9a9d; |
||||
|
text-decoration: line-through; |
||||
|
margin-left: 30upx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.mp-btn { |
||||
|
flex-shrink: 0; |
||||
|
flex-grow: 0; |
||||
|
position: relative; |
||||
|
margin-left: 10upx; |
||||
|
width: 36upx; |
||||
|
height: 36upx; |
||||
|
border-radius: 50%; |
||||
|
background-color: $mColor; |
||||
|
&::before, |
||||
|
&::after { |
||||
|
content: ''; |
||||
|
display: block; |
||||
|
position: absolute; |
||||
|
left: 50%; |
||||
|
top: 50%; |
||||
|
transform: translate(-50%, -50%); |
||||
|
background-color: #fff; |
||||
|
border-radius: 2upx; |
||||
|
width: 20upx; |
||||
|
height: 4upx; |
||||
|
} |
||||
|
&::after { |
||||
|
height: 20upx; |
||||
|
width: 4upx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.mg-tip { |
||||
|
height: 200upx; |
||||
|
line-height: 200upx; |
||||
|
text-align: center; |
||||
|
font-size: 28upx; |
||||
|
color: #9a9a9d; |
||||
|
background-color: #f2f2f7; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
After Width: 12 | Height: 14 | Size: 169 B |
After Width: 12 | Height: 14 | Size: 165 B |
Write
Preview
Loading…
Cancel
Save
Reference in new issue