From b828866cc5a4044e85e44a2b76dd1d8ae186a3ad Mon Sep 17 00:00:00 2001 From: June <1601745371@qq.com> Date: Fri, 3 Sep 2021 18:01:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=95=86=E5=93=81=E5=88=86=E7=BB=84?= =?UTF-8?q?=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 2 +- apis/category.js | 28 +-- config/index.js | 2 +- ext.json | 4 +- lib/service/index.js | 39 ++++ pages/category/index-1.vue | 383 +++++++++++++++++++++++++++++++++++++ pages/category/index.vue | 244 +++++++++++------------ 7 files changed, 564 insertions(+), 138 deletions(-) create mode 100644 pages/category/index-1.vue diff --git a/App.vue b/App.vue index 1f50de0..47d99e2 100644 --- a/App.vue +++ b/App.vue @@ -5,7 +5,7 @@ import dayjs from 'dayjs' import { removeStorage } from '@/lib/storage/index.js' export default { onLaunch: async function() { - await this.checkUpdate() // 检查更新 + this.checkUpdate() // 检查更新 this.setMobileData() // 获å–系统信æ¯å’Œèƒ¶å›Šä¿¡æ¯ const extConfig = wx.getExtConfigSync ? wx.getExtConfigSync(): {} this.$store.state.user.appid = extConfig.appid diff --git a/apis/category.js b/apis/category.js index 0f2404b..2508780 100644 --- a/apis/category.js +++ b/apis/category.js @@ -1,31 +1,33 @@ import { request } from "@/lib/service" -/** - * @desc 获å–分类列表 - */ -export function getCatetories() { - return request({ - url: 'zsxcx/shopGoodsCategory.htm', - method: 'post' - }) -} - /** * @desc 店铺商å“åˆ—è¡¨æŽ¥å£ * @param { String } keywords 关键å—:商å“åç§° * @param { Number } cat_id * 分类ID */ -export function cateGoodsList(cat_id, keywords = '') { +export function cateGoodsList({cat_id, keywords = '', page = 1, pagenum = 10}) { return request({ - url: 'zsxcx/shopGoods.htm', + url: 'zsxcx/shopGoodsCustom.htm', method: 'post', data: { cat_id, - keywords + keywords, + page, + pagenum } }) } +/** + * 店铺商å“分组分类 + */ +export function groupCates() { + return request({ + url: 'zsxcx/shopGoodsCategoryCustom.htm', + method: 'post' + }) +} + /** * @desc 首页展示æ å•†å“æŽ¥å£ */ diff --git a/config/index.js b/config/index.js index 0ed0159..d1e4703 100644 --- a/config/index.js +++ b/config/index.js @@ -1,7 +1,7 @@ const env = { release: 'https://www.gelifood.com', // æ£å¼ç‰ˆ trial: 'https://www.gelifood.com', // 体验版 - develop: 'https://www.gelifood.com' // å¼€å‘版 + develop: 'https://d.gelifood.com' // å¼€å‘版 } // ä¸è€ƒè™‘其他端å°ç¨‹åºç›´æŽ¥è¿™æ ·é…ç½® diff --git a/ext.json b/ext.json index 52caba0..96480dc 100644 --- a/ext.json +++ b/ext.json @@ -1,7 +1,7 @@ { "extEnable": true, - "extAppid": "wx537e892e36fbf79d", + "extAppid": "wxd170058f4ad8fecd", "ext": { - "appid": "wx537e892e36fbf79d" + "appid": "wxd170058f4ad8fecd" } } \ No newline at end of file diff --git a/lib/service/index.js b/lib/service/index.js index f14910e..3e1e5f1 100644 --- a/lib/service/index.js +++ b/lib/service/index.js @@ -147,6 +147,45 @@ export function request (options) { }) } +// 请求 +// export function testrequest (options) { +// const valite_err = validateOps(options) +// if(valite_err) return Toast({title: valite_err}) +// options.method = options.method ? options.method.toUpperCase() : "GET" // 默认get +// options.url = `${options.url}` +// if(options.needMask) { +// uni.showLoading({title: 'åŠ è½½ä¸...', mask: true}) +// } +// return new Promise((resolve, reject) => { +// const token = store.state.user.token || '' +// const appid = store.state.user.appid || '' +// uni.request({ +// ...options, +// header: { +// 'content-type': 'application/x-www-form-urlencoded', +// 'token': token, +// 'appid': appid +// }, +// success: res => { +// successRes(res, options, resolve, reject) +// }, +// fail: err => { +// Toast({title: '网络开å°å·®äº†,请检查网络!'}) +// options.errCb && typeof options.errCb === 'function' && options.errCb(); +// reject({ +// status: false, +// code: 400, +// data: err +// }) +// }, +// complete: () => { +// options.completeCb && typeof options.completeCb === 'function' && options.completeCb(); +// options.needMask && uni.hideLoading() +// } +// }) +// }) +// } + // ä¸Šä¼ æ–‡ä»¶ export function upload(options) { const valite_err = validateOps(options) diff --git a/pages/category/index-1.vue b/pages/category/index-1.vue new file mode 100644 index 0000000..0f734c0 --- /dev/null +++ b/pages/category/index-1.vue @@ -0,0 +1,383 @@ +<template> + <view class="category-wrap w-100"> + <template v-if="isOverdue"> + <view style="width: 100vw; height: 100vh;display: flex;justify-content: center;align-items: center;"> + <over-due /> + </view> + </template> + + + <template v-else> + <!-- search bar --> + <view class="searchBar-wrap flex j-center a-center w-100"> + <navigator + class="search flex j-center a-center" + hover-class="none" + url="/pages/search/index" + > + <image class="search-icon mr-1" src="/static/images/common/icon-search.png" mode="aspectFit" /> + <text class="font-24">æœç´¢å•†å“</text> + </navigator> + </view> + + <!-- category 未优化,å¯ä»¥é€’归组件 --> + <template v-if="goods_list.length === 0"> + <view class="flex j-center a-center w-100 category"> + <empty-view + iconSrc="/static/images/common/noGoods.png" + text="店铺尚未上架商å“" + /> + </view> + </template> + <template v-else> + <view class="category flex j-between w-100 font-24"> + <scroll-view + class="scroll-left" + scroll-y + :scroll-into-view="leftScrollName" + > + <!-- 一级分类 --> + <view + class="w-100 px-3 py-2" + v-for="(cate_1, cate_idx_1) in cate_list" + :key="cate_1.cat_id" + :class="cate1_current === cate_1.cat_id ? 'cate-active' : null" + @click.stop="" + > + + <view + class="mb-2" + @click.stop="cateChange(1, cate_1.cat_id, cate_idx_1)" + :class="cate1_current === cate_1.cat_id ? 'cate-1_active' : null" + >{{cate_1.cat_name}}</view> + <view v-show="cate1_current === cate_1.cat_id && cate_1.list.length > 0"> + + <!-- 二级分类 --> + <view + class="ml-2 second-item" + v-for="(cate_2, cate_idx_2) in cate_1.list" + :key="cate_2.cat_id" + > + <view + :class="cate2_current === cate_2.cat_id ? 'cate-2_active' : null" + @click.stop="cateChange(2, cate_2.cat_id, cate_idx_1, cate_idx_2)" + >{{cate_2.cat_name}}</view> + </view> + + </view> + + </view> + </scroll-view> + + <view class="scroll-right flex-1"> + <view class="cates_title">{{cate1_name}} {{cate2_name ? '-' + cate2_name : ''}}</view> + <pull-list + ref="pullList" + :refresherEnabled="false" + > + + <view + class="goods-item flex j-start a-center" + v-for="good in goods_list" + :key="good.goods_id" + @click="navDetail(good)" + > + <image + class="goods-cover mr-2" + lazy-load + :src="baseUrl + '/' + good.goods_thumb" + mode="aspectFit" + /> + <view class="goods-price flex-1 flex flex-column j-between font-28"> + <view class="title">{{good.goods_name}}</view> + <view class="descColor desc font-24 w-100 flex j-between a-center"> + <text class="flex-1">{{good.specification}}</text> + <text class="sale-count text-right">销é‡ï¼š{{good.virtual_quantity_sold}}</text> + </view> + <view class="w-100 flex j-between a-center"> + <view class="flex j-start a-center"> + <price + :is_inquiry="good.is_inquiry" + :price="good.shop_price" + /> + <text class="primaryColor font-28">{{good.least_str}}</text> + </view> + <image + class="cart-icon" + src="/static/images/common/icon-cart.png" + mode="aspectFit" + @click.stop="handlePop(good)" + /> + </view> + </view> + </view> + + <view class="empty-text text-center mt-4 p-2">到底了,看看别的分类å§~</view> + + </pull-list> + </view> + </view> + </template> + + + <!-- è´ç‰©å¼¹çª— --> + <goods-popup ref="popup" :fitIphoneX="false" /> + </template> + </view> +</template> + +<script> +// 所有写法需è¦ä¼˜åŒ–ï¼ï¼ï¼ +import pullList from '@/components/pull-list/index.vue' +import goodsPopup from '@/components/goods-popup/index.vue' +import overDue from '@/components/overDue-view/index.vue' +import price from '@/components/price/index.vue' + +import { getCatetories, cateGoodsList } from '@/apis/category.js' +import { searchGoods, goodsSku } from '@/apis/goods.js' +import { baseUrl } from '@/config/index.js' +import common_share from '@/mixins/setting_share.js' +import { mapState, mapActions } from 'vuex' +import { debounce } from '@/utils/common.js' +let cat_id = 0 + +export default { + data() { + return { + baseUrl, + cate1_current: '1', // å’Œcateid对应则未选ä¸çŠ¶æ€ + cate2_current: '0', + cate1_name: '', + cate2_name: '', + cate_list: [], // 分类列表 + goods_list: [], // 分类商å“列表 + showNoMoreMsg: false + } + }, + components: { + pullList, + goodsPopup, + overDue, + price + }, + computed: { + ...mapState({ + token: state => state.user.token, + isOverdue: state => state.user.isOverdue + }) + }, + // async created() { + // this.getCate() + // }, + onShow() { + uni.showLoading() + this.getCate() + this.getCateGoods() + if(this.token) { + this.setCount() + } + uni.hideLoading() + }, + mixins: [common_share], + methods: { + ...mapActions('cart', ['setCount']), + async getCate() { + try{ + const { status, data } = await getCatetories() + if(status) { + let cate_list = this.cate_list + cate_list = data + cat_id = cate_list[0].cat_id + this.cate1_current = cate_list[0].cat_id + this.cate_list = cate_list + this.cate1_name = cate_list[0].cat_name + // this.cate2_name = cate_list[0].list[0].cat_name + this.getCateGoods() + } + }catch(e){ + console.log(e) + this.$toast({title: e.msg || '获å–分类失败'}) + } + }, + + // 切æ¢åˆ†ç±» type === 1 分类1 type === 2 分类2, cate1_idx 分类一的下表 + cateChange(type, cate_id, cate1_idx, cate2_idx) { + if(cat_id === cate_id) return + const cate_list = this.cate_list + if(type === 1) { + this.cate1_current = cate_id + this.cate2_current = "0" // åˆå§‹åŒ–,让二级ä¸åœ¨æ¿€æ´»çŠ¶æ€ + cat_id = cate_id + this.cate1_name = cate_list[cate1_idx].cat_name + this.cate2_name = '' + } else if(type === 2) { + this.cate2_current = cate_id + cat_id = cate_id + this.cate2_name = cate_list[cate1_idx].list[cate2_idx].cat_name + } + this.$refs.pullList.scroll2Top() + this.getCateGoods() + }, + + // 获å–åˆ†ç±»å•†å“ + async getCateGoods() { + try{ + const { status, data } = await cateGoodsList(cat_id) + if(status) { + this.goods_list = data + } else { + this.goods_list = [] + } + }catch(e){ + console.log(e) + this.$toast({title: e.msg || '程åºé”™è¯¯'}) + } + }, + + // 商å“详情 + navDetail(good) { + uni.navigateTo({ + url: `/pages/goods/detail?goods_id=${good.goods_id}&shop_id=${good.shop_id}&agent_id=${good.agent_id}` + }) + }, + + // tolower() { + // console.log('触底了') + // }, + + // 点击拉起弹窗 + handlePop: debounce(async function(goods) { + try{ + uni.showLoading({ + title: 'åŠ è½½ä¸...', + mask: true + }) + const { status, data } = await goodsSku(goods.goods_id) + if(status) { + console.log(data) + const params = { + goodsInfo: { + cover: `${this.baseUrl}/${goods.goods_thumb}`, + title: goods.goods_name, + is_inquiry: goods.is_inquiry, + unit: goods.goods_unit + }, + skuData: data + } + console.log(params) + this.$refs.popup.show(params) + } + uni.hideLoading() + }catch(e){ + console.log(e) + uni.hideLoading() + //TODO handle the exception + } + }, 800) + } +} +// disableScroll: true +</script> + +<style lang="scss" scoped> +.category-wrap { + height: 100vh; + box-sizing: border-box; + border-top: 1rpx solid $line; + overflow: hidden; + .searchBar-wrap { + height: 112rpx; + background-color: #fff; + .search { + width: 690rpx; + height: 72rpx; + border-radius: 4rpx; + background-color: $mainBg; + .search-icon { + width: 32rpx; + height: 32rpx; + } + } + } + + .category{ + height: calc(100vh - 112rpx); + background-color: $mainBg; + overflow: hidden; + .scroll-left { + flex: 0 0 180rpx; + overflow: hidden; + .cate-1_active { + color: $primary; + font-weight: bold; + } + .cate-2_active { + color: $primary; + } + .cate-active { + background-color: #fff; + } + + .second-item { + margin-bottom: 20rpx; + &:last-child { + margin-bottom: 0; + } + } + } + + .scroll-right { + position: relative; + padding-top: 72rpx; + background-color: #fff; + .cates_title { + position: absolute; + left: 0; + top: 0; + right: 0; + z-index: 2; + height: 72rpx; + line-height: 72rpx; + margin-left: 20rpx; + background-color: #fff; + } + .empty-text { + font-size: 20rpx; + color: $desc; + } + + .goods-item { + @include borderBox(20rpx, 20rpx); + border-bottom: 1rpx solid $line; + .goods-cover { + flex: 0 0 160rpx; + width: 160rpx; + height: 160rpx; + } + .goods-price { + height: 160rpx; + .title { + @include text-ellipsis(1); + color: #343434; + } + .desc{ + .spec { + @include text-ellipsis(1); + } + .sale-count { + flex: 0 0 200rpx; + } + } + .price-txt { + color: $primary; + } + .cart-icon { + width: 34rpx; + height: 32rpx; + } + } + } + } + } +} +</style> diff --git a/pages/category/index.vue b/pages/category/index.vue index 0f734c0..88d7f6f 100644 --- a/pages/category/index.vue +++ b/pages/category/index.vue @@ -19,9 +19,8 @@ <text class="font-24">æœç´¢å•†å“</text> </navigator> </view> - - <!-- category 未优化,å¯ä»¥é€’归组件 --> - <template v-if="goods_list.length === 0"> + + <template v-if="cate_list.length === 0"> <view class="flex j-center a-center w-100 category"> <empty-view iconSrc="/static/images/common/noGoods.png" @@ -35,90 +34,78 @@ class="scroll-left" scroll-y :scroll-into-view="leftScrollName" + @click="handleCate" > - <!-- 一级分类 --> - <view - class="w-100 px-3 py-2" - v-for="(cate_1, cate_idx_1) in cate_list" - :key="cate_1.cat_id" - :class="cate1_current === cate_1.cat_id ? 'cate-active' : null" - @click.stop="" + <view + class="cate-item overtext-1" + :class="cate_cur === cate_idx ? 'cate-active' : null" + v-for="(cate, cate_idx) in cate_list" + :key="cate.id" + :data-index="cate_idx" > - - <view - class="mb-2" - @click.stop="cateChange(1, cate_1.cat_id, cate_idx_1)" - :class="cate1_current === cate_1.cat_id ? 'cate-1_active' : null" - >{{cate_1.cat_name}}</view> - <view v-show="cate1_current === cate_1.cat_id && cate_1.list.length > 0"> - - <!-- 二级分类 --> - <view - class="ml-2 second-item" - v-for="(cate_2, cate_idx_2) in cate_1.list" - :key="cate_2.cat_id" - > - <view - :class="cate2_current === cate_2.cat_id ? 'cate-2_active' : null" - @click.stop="cateChange(2, cate_2.cat_id, cate_idx_1, cate_idx_2)" - >{{cate_2.cat_name}}</view> - </view> - - </view> - + {{cate.cat_name}} </view> </scroll-view> <view class="scroll-right flex-1"> - <view class="cates_title">{{cate1_name}} {{cate2_name ? '-' + cate2_name : ''}}</view> - <pull-list - ref="pullList" - :refresherEnabled="false" - > - - <view - class="goods-item flex j-start a-center" - v-for="good in goods_list" - :key="good.goods_id" - @click="navDetail(good)" - > - <image - class="goods-cover mr-2" - lazy-load - :src="baseUrl + '/' + good.goods_thumb" - mode="aspectFit" + <template v-if="goods_list.length === 0"> + <view class="flex j-center a-center w-100 empty-wrap"> + <empty-view + iconSrc="/static/images/common/noGoods.png" + text="è¯¥åˆ†ç±»æš‚æ— å•†å“" /> - <view class="goods-price flex-1 flex flex-column j-between font-28"> - <view class="title">{{good.goods_name}}</view> - <view class="descColor desc font-24 w-100 flex j-between a-center"> - <text class="flex-1">{{good.specification}}</text> - <text class="sale-count text-right">销é‡ï¼š{{good.virtual_quantity_sold}}</text> - </view> - <view class="w-100 flex j-between a-center"> - <view class="flex j-start a-center"> - <price - :is_inquiry="good.is_inquiry" - :price="good.shop_price" + </view> + </template> + <template v-else> + <view class="cates_title">{{cate_name}}</view> + <pull-list + ref="pullList" + :refresherEnabled="false" + > + + <view + class="goods-item flex j-start a-center" + v-for="good in goods_list" + :key="good.goods_id" + @click="navDetail(good)" + > + <image + class="goods-cover mr-2" + lazy-load + :src="baseUrl + '/' + good.goods_thumb" + mode="aspectFit" + /> + <view class="goods-price flex-1 flex flex-column j-between font-28"> + <view class="title">{{good.goods_name}}</view> + <view class="descColor desc font-24 w-100 flex j-between a-center"> + <text class="flex-1">{{good.specification}}</text> + <text class="sale-count text-right">销é‡ï¼š{{good.virtual_quantity_sold}}</text> + </view> + <view class="w-100 flex j-between a-center"> + <view class="flex j-start a-center"> + <price + :is_inquiry="good.is_inquiry" + :price="good.shop_price" + /> + <text class="primaryColor font-28">{{good.least_str}}</text> + </view> + <image + class="cart-icon" + src="/static/images/common/icon-cart.png" + mode="aspectFit" + @click.stop="handlePop(good)" /> - <text class="primaryColor font-28">{{good.least_str}}</text> </view> - <image - class="cart-icon" - src="/static/images/common/icon-cart.png" - mode="aspectFit" - @click.stop="handlePop(good)" - /> </view> </view> - </view> - - <view class="empty-text text-center mt-4 p-2">到底了,看看别的分类å§~</view> - - </pull-list> + + <view class="empty-text text-center mt-4 p-2">到底了,看看别的分类å§~</view> + + </pull-list> + </template> </view> </view> </template> - <!-- è´ç‰©å¼¹çª— --> <goods-popup ref="popup" :fitIphoneX="false" /> @@ -127,28 +114,24 @@ </template> <script> -// 所有写法需è¦ä¼˜åŒ–ï¼ï¼ï¼ import pullList from '@/components/pull-list/index.vue' import goodsPopup from '@/components/goods-popup/index.vue' import overDue from '@/components/overDue-view/index.vue' import price from '@/components/price/index.vue' -import { getCatetories, cateGoodsList } from '@/apis/category.js' -import { searchGoods, goodsSku } from '@/apis/goods.js' -import { baseUrl } from '@/config/index.js' +import { cateGoodsList, groupCates } from '@/apis/category.js' +import { goodsSku } from '@/apis/goods.js' import common_share from '@/mixins/setting_share.js' import { mapState, mapActions } from 'vuex' import { debounce } from '@/utils/common.js' +import LoadMore from '@/utils/load-more.js' let cat_id = 0 export default { data() { return { - baseUrl, - cate1_current: '1', // å’Œcateid对应则未选ä¸çŠ¶æ€ - cate2_current: '0', - cate1_name: '', - cate2_name: '', + cate_cur: 0, + cate_name: '', cate_list: [], // 分类列表 goods_list: [], // 分类商å“列表 showNoMoreMsg: false @@ -166,32 +149,32 @@ export default { isOverdue: state => state.user.isOverdue }) }, - // async created() { - // this.getCate() - // }, + + created() { + this.loadMore = new LoadMore() + }, + onShow() { uni.showLoading() this.getCate() - this.getCateGoods() if(this.token) { this.setCount() } uni.hideLoading() }, + mixins: [common_share], + methods: { ...mapActions('cart', ['setCount']), + async getCate() { try{ - const { status, data } = await getCatetories() + const { status, data } = await groupCates() if(status) { - let cate_list = this.cate_list - cate_list = data - cat_id = cate_list[0].cat_id - this.cate1_current = cate_list[0].cat_id - this.cate_list = cate_list - this.cate1_name = cate_list[0].cat_name - // this.cate2_name = cate_list[0].list[0].cat_name + this.cate_list = data + cat_id = data[0].id + this.cate_name = data[0].cat_name this.getCateGoods() } }catch(e){ @@ -199,7 +182,36 @@ export default { this.$toast({title: e.msg || '获å–分类失败'}) } }, + + // 切æ¢åˆ†ç±» + handleCate(e) { + const { index } = e.target.dataset + if(this.cate_cur === index) return + const cate_list = this.cate_list + this.cate_cur = index + cat_id = cate_list[index].id + this.cate_name = cate_list[index].cat_name + this.loadMore.resetParams() + this.getCateGoods() + }, + // 获å–åˆ†ç±»å•†å“ + async getCateGoods() { + try{ + const { status, data } = await this.loadMore.getList({cat_id}, cateGoodsList) + + if(status) { + this.goods_list = data + this.cate + } else { + this.goods_list = [] + } + }catch(e){ + console.log(e) + this.$toast({title: e.msg || '程åºé”™è¯¯'}) + } + }, + // 切æ¢åˆ†ç±» type === 1 分类1 type === 2 分类2, cate1_idx 分类一的下表 cateChange(type, cate_id, cate1_idx, cate2_idx) { if(cat_id === cate_id) return @@ -219,20 +231,6 @@ export default { this.getCateGoods() }, - // 获å–åˆ†ç±»å•†å“ - async getCateGoods() { - try{ - const { status, data } = await cateGoodsList(cat_id) - if(status) { - this.goods_list = data - } else { - this.goods_list = [] - } - }catch(e){ - console.log(e) - this.$toast({title: e.msg || '程åºé”™è¯¯'}) - } - }, // 商å“详情 navDetail(good) { @@ -306,30 +304,34 @@ export default { overflow: hidden; .scroll-left { flex: 0 0 180rpx; + width: 180rpx; overflow: hidden; - .cate-1_active { - color: $primary; - font-weight: bold; - } - .cate-2_active { - color: $primary; + .cate-item { + box-sizing: border-box; + width: 100%; + height: 80rpx; + padding: 0 10rpx; + line-height: 80rpx; + text-align: center; } .cate-active { + font-weight: bold; + color: $primary; background-color: #fff; } - - .second-item { - margin-bottom: 20rpx; - &:last-child { - margin-bottom: 0; - } - } } .scroll-right { position: relative; padding-top: 72rpx; background-color: #fff; + .empty-wrap { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + } .cates_title { position: absolute; left: 0; -- 2.24.1