商品分类:列表

pull/26/head^2
YunaiV 2023-12-10 22:12:33 +08:00
parent e971e09593
commit 8fd8ff9f70
6 changed files with 258 additions and 224 deletions

View File

@ -1,36 +1,53 @@
<!-- 分类列表 --> <!-- 商品分类列表 -->
<template> <template>
<s-layout title="分类" tabbar="/pages/index/category" :bgStyle="{ color: '#fff' }"> <s-layout title="分类" tabbar="/pages/index/category" :bgStyle="{ color: '#fff' }">
<view class="s-category"> <view class="s-category">
<view class="three-level-wrap ss-flex ss-col-top" :style="[{ height: pageHeight + 'px' }]"> <view class="three-level-wrap ss-flex ss-col-top" :style="[{ height: pageHeight + 'px' }]">
<!-- 商品分类 --> <!-- 商品分类 -->
<scroll-view class="side-menu-wrap" scroll-y :style="[{ height: pageHeight + 'px' }]"> <scroll-view class="side-menu-wrap" scroll-y :style="[{ height: pageHeight + 'px' }]">
<view class="menu-item ss-flex" v-for="(item, index) in state.categoryList?.children" :key="item.id" <view
:class="[{ 'menu-item-active': index == state.activeMenu }]" @tap="onMenu(index)"> class="menu-item ss-flex"
v-for="(item, index) in state.categoryList"
:key="item.id"
:class="[{ 'menu-item-active': index === state.activeMenu }]"
@tap="onMenu(index)"
>
<view class="menu-title ss-line-1"> <view class="menu-title ss-line-1">
{{ item.name }} {{ item.name }}
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
<!-- 商品分类 --> <!-- 商品分类 -->
<scroll-view class="goods-list-box" scroll-y :style="[{ height: pageHeight + 'px' }]" <scroll-view
v-if="state.categoryList?.children?.length"> class="goods-list-box"
<image v-if="state.categoryList.children[state.activeMenu].image" class="banner-img" scroll-y
:src="sheep.$url.cdn(state.categoryList.children[state.activeMenu].image)" mode="widthFix"> :style="[{ height: pageHeight + 'px' }]"
</image> v-if="state.categoryList?.length"
<first-one v-if="state.categoryList.style === 'first_one'" :data="state.categoryList" >
:activeMenu="state.activeMenu" :pagination="state.pagination" /> <image
<first-two v-if="state.categoryList.style === 'first_two'" :data="state.categoryList" v-if="state.categoryList[state.activeMenu].picUrl"
:activeMenu="state.activeMenu" :pagination="state.pagination" /> class="banner-img"
<second-one v-if="state.categoryList.style === 'second_one'" :data="state.categoryList" :src="sheep.$url.cdn(state.categoryList[state.activeMenu].picUrl)"
:activeMenu="state.activeMenu" :pagination="state.pagination" /> mode="widthFix"
<uni-load-more v-if=" />
(state.categoryList.style === 'first_one' || <first-one v-if="state.style === 'first_one'" :pagination="state.pagination" />
state.categoryList.style === 'first_two') && <first-two v-if="state.style === 'first_two'" :pagination="state.pagination" />
<second-one
v-if="state.style === 'second_one'"
:data="state.categoryList"
:activeMenu="state.activeMenu"
/>
<uni-load-more
v-if="
(state.style === 'first_one' || state.style === 'first_two') &&
state.pagination.total > 0 state.pagination.total > 0
" :status="state.loadStatus" :content-text="{ "
:status="state.loadStatus"
:content-text="{
contentdown: '点击查看更多', contentdown: '点击查看更多',
}" @tap="loadmore" /> }"
@tap="loadMore"
/>
</scroll-view> </scroll-view>
</view> </view>
</view> </view>
@ -42,27 +59,24 @@
import firstOne from './components/first-one.vue'; import firstOne from './components/first-one.vue';
import firstTwo from './components/first-two.vue'; import firstTwo from './components/first-two.vue';
import sheep from '@/sheep'; import sheep from '@/sheep';
import CategoryApi from '@/sheep/api/product/category';
import { import SpuApi from '@/sheep/api/product/spu';
onLoad, import { onLoad, onReachBottom } from '@dcloudio/uni-app';
onReachBottom import { computed, reactive } from 'vue';
} from '@dcloudio/uni-app';
import {
computed,
reactive
} from 'vue';
import _ from 'lodash'; import _ from 'lodash';
import { handleTree } from '@/sheep/util'; import { handleTree } from '@/sheep/util';
const state = reactive({ const state = reactive({
style: 'second_one', // first_one - , first_two - , second_one style: 'second_one', // first_one - , first_two - , second_one
categoryList: [], // categoryList: [], //
activeMenu: '0', activeMenu: 0, // categoryList
pagination: { pagination: {
data: [], //
current_page: 1, list: [], //
total: 1, total: [], //
last_page: 1, pageNo: 1,
pageSize: 6,
}, },
loadStatus: '', loadStatus: '',
}); });
@ -70,74 +84,63 @@
const { safeArea } = sheep.$platform.device; const { safeArea } = sheep.$platform.device;
const pageHeight = computed(() => safeArea.height - 44 - 50); const pageHeight = computed(() => safeArea.height - 44 - 50);
async function getList(options) { //
const { async function getList() {
code, const { code, data } = await CategoryApi.getCategoryList();
data if (code !== 0) {
} = await sheep.$api.category.list({ return;
id: options.id,
});
if (code === 0) {
state.categoryList = {
children: handleTree(data),
style: 'second_one'
};
} }
state.categoryList = handleTree(data);
} }
//
const onMenu = (val) => { const onMenu = (val) => {
state.activeMenu = val; state.activeMenu = val;
if (state.categoryList.style === 'first_one' || state.categoryList.style === 'first_two') { if (state.style === 'first_one' || state.style === 'first_two') {
state.pagination = { state.pagination.pageNo = 1;
data: [], state.pagination.list = [];
current_page: 1, state.pagination.total = 0;
total: 1, getGoodsList();
last_page: 1,
};
getGoodsList(state.categoryList.children[val].id);
} }
//
// getGoodsList(state.categoryList.children[val].id);
}; };
async function getGoodsList(id, page = 1, list_rows = 6) { //
async function getGoodsList() {
//
state.loadStatus = 'loading'; state.loadStatus = 'loading';
const res = await sheep.$api.goods.list({ const res = await SpuApi.getSpuPage({
categoryId: id, categoryId: state.categoryList[state.activeMenu].id,
pageSize: list_rows, pageNo: state.pagination.pageNo,
pageNo: page, pageSize: state.pagination.pageSize,
}); });
if (res.code === 0) { if (res.code !== 0) {
let couponList = _.concat(state.pagination.data, res.data.list); return;
state.pagination = {
...res.data,
data: couponList,
};
console.log(state.pagination)
if (state.pagination.current_page < state.pagination.last_page) {
state.loadStatus = 'more';
} else {
state.loadStatus = 'noMore';
} }
//
state.pagination.list = _.concat(state.pagination.list, res.data.list);
state.pagination.total = res.data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
} }
//
function loadMore() {
if (state.loadStatus === 'noMore') {
return;
} }
// state.pagination.pageNo++;
function loadmore() { getGoodsList();
if (state.loadStatus !== 'noMore') {
getGoodsList(
state.categoryList.children[state.activeMenu].id,
state.pagination.current_page + 1,
);
} }
}
onLoad(async (options) => { onLoad(async () => {
await getList(options); await getList();
if (state.categoryList.style === 'first_one' || state.categoryList.style === 'first_two') { // first
getGoodsList(state.categoryList.children[0].id); if (state.style === 'first_one' || state.style === 'first_two') {
onMenu(0);
} }
}); });
onReachBottom(() => { onReachBottom(() => {
loadmore(); loadMore();
}); });
</script> </script>
@ -169,9 +172,11 @@
content: ''; content: '';
width: 64rpx; width: 64rpx;
height: 12rpx; height: 12rpx;
background: linear-gradient(90deg, background: linear-gradient(
90deg,
var(--ui-BG-Main-gradient), var(--ui-BG-Main-gradient),
var(--ui-BG-Main-light)) !important; var(--ui-BG-Main-light)
) !important;
position: absolute; position: absolute;
left: -64rpx; left: -64rpx;
bottom: 0; bottom: 0;

View File

@ -1,23 +1,20 @@
<!-- 分类展示first-one 风格 -->
<template> <template>
<view class="ss-flex-col"> <view class="ss-flex-col">
<view class="goods-box" v-for="item in pagination.data" :key="item.id"> <view class="goods-box" v-for="item in pagination.list" :key="item.id">
<s-goods-column <s-goods-column
size="sl" size="sl"
:data="item" :data="item"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })" @click="sheep.$router.go('/pages/goods/index', { id: item.id })"
></s-goods-column> />
</view> </view>
</view> </view>
</template> </template>
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
const props = defineProps({ const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
activeMenu: [Number, String],
pagination: Object, pagination: Object,
}); });
</script> </script>

View File

@ -1,15 +1,15 @@
<!-- 页面 --> <!-- 分类展示first-two 风格 -->
<template> <template>
<view> <view>
<view class="ss-flex flex-wrap"> <view class="ss-flex flex-wrap">
<view class="goods-box" v-for="item in pagination?.data" :key="item.id"> <view class="goods-box" v-for="item in pagination?.list" :key="item.id">
<view @click="sheep.$router.go('/pages/goods/index', { id: item.id })"> <view @click="sheep.$router.go('/pages/goods/index', { id: item.id })">
<view class="goods-img"> <view class="goods-img">
<image class="goods-img" :src="sheep.$url.cdn(item.image)" mode="aspectFit"></image> <image class="goods-img" :src="item.picUrl" mode="aspectFit" />
</view> </view>
<view class="goods-content"> <view class="goods-content">
<view class="goods-title ss-line-1 ss-m-b-28">{{ item.title }}</view> <view class="goods-title ss-line-1 ss-m-b-28">{{ item.title }}</view>
<view class="goods-price">{{ item.price[0] }}</view> <view class="goods-price">{{ fen2yuan(item.price) }}</view>
</view> </view>
</view> </view>
</view> </view>
@ -19,12 +19,9 @@
<script setup> <script setup>
import sheep from '@/sheep'; import sheep from '@/sheep';
import { fen2yuan } from '@/sheep/hooks/useGoods';
const props = defineProps({ const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
activeMenu: [Number, String],
pagination: Object, pagination: Object,
}); });
</script> </script>

View File

@ -4,14 +4,14 @@
<!-- 一级分类的名字 --> <!-- 一级分类的名字 -->
<view class="title-box ss-flex ss-col-center ss-row-center ss-p-b-30"> <view class="title-box ss-flex ss-col-center ss-row-center ss-p-b-30">
<view class="title-line-left" /> <view class="title-line-left" />
<view class="title-text ss-p-x-20">{{ props.data.children[activeMenu].name }}</view> <view class="title-text ss-p-x-20">{{ props.data[activeMenu].name }}</view>
<view class="title-line-right" /> <view class="title-line-right" />
</view> </view>
<!-- 二级分类的名字 --> <!-- 二级分类的名字 -->
<view class="goods-item-box ss-flex ss-flex-wrap ss-p-b-20"> <view class="goods-item-box ss-flex ss-flex-wrap ss-p-b-20">
<view <view
class="goods-item" class="goods-item"
v-for="item in props.data.children[activeMenu].children" v-for="item in props.data[activeMenu].children"
:key="item.id" :key="item.id"
@tap=" @tap="
sheep.$router.go('/pages/goods/list', { sheep.$router.go('/pages/goods/list', {
@ -36,7 +36,7 @@
type: Object, type: Object,
default: () => ({}), default: () => ({}),
}, },
activeMenu: [Number, String] activeMenu: [Number, String],
}); });
</script> </script>

View File

@ -0,0 +1,12 @@
import request from '@/sheep/request';
const CategoryApi = {
// 查询分类列表
getCategoryList: () => {
return request({
url: '/app-api/product/category/list',
method: 'GET'
});
}
};
export default CategoryApi;

View File

@ -53,8 +53,6 @@ export const convertToInteger = (num) => {
return Math.round(parsedNumber * 100) return Math.round(parsedNumber * 100)
} }
/** /**
* 时间日期转换 * 时间日期转换
* @param {dayjs.ConfigType} date 当前时间new Date() 格式 * @param {dayjs.ConfigType} date 当前时间new Date() 格式
@ -77,3 +75,28 @@ export function formatDate(date, format) {
} }
return dayjs(date).format(format) return dayjs(date).format(format)
} }
/**
* 构造树型结构数据
*
* @param {*} data 数据源
* @param {*} id id字段 默认 'id'
* @param {*} parentId 父节点字段 默认 'parentId'
* @param {*} children 孩子节点字段 默认 'children'
* @param {*} rootId 根Id 默认 0
*/
export function handleTree(data, id = 'id', parentId = 'parentId', children = 'children', rootId = 0) {
// 对源数据深度克隆
const cloneData = JSON.parse(JSON.stringify(data))
// 循环所有项
const treeData = cloneData.filter(father => {
let branchArr = cloneData.filter(child => {
//返回每一项的子级数组
return father[id] === child[parentId]
});
branchArr.length > 0 ? father.children = branchArr : '';
//返回第一层
return father[parentId] === rootId;
});
return treeData !== '' ? treeData : data;
}