feat(产品)
This commit is contained in:
parent
dbd3b1f839
commit
78d6d7df1f
|
@ -1,20 +1,69 @@
|
||||||
<template>
|
<template>
|
||||||
<pb-layout
|
<pb-layout title="产品" navbar="normal" tabbar="/pages/index/product" :bgStyle="bgStyle" opacityBgUi="bg-white"
|
||||||
title="分类"
|
color="black">
|
||||||
navbar="normal"
|
|
||||||
tabbar="/pages/index/category"
|
<view v-if="StaticRange.pagination.total > 0" class="goods-list ss-m-t-20">
|
||||||
:bgStyle="bgStyle"
|
<view class="ss-p-l-20 ss-p-r-20" v-for="item in state.pagination.list" :key="item.id">
|
||||||
opacityBgUi="bg-white"
|
<p-goods-column size="lg" :data="item" :topRadius="10" bottomRadius="10"
|
||||||
color="black"
|
@click="peach.$router.go('/pages/goods/index', { id: item.id })" />
|
||||||
>
|
</view>
|
||||||
<p-empty icon="/static/soldout-empty.png" text="暂无内容" />
|
</view>
|
||||||
</pb-layout>
|
|
||||||
|
<uni-load-more v-if="StaticRange.pagination.total > 0" :status="StaticRange.loadStatus" :content-text="{
|
||||||
|
contentdown: '上拉加载更多'
|
||||||
|
}" @click="loadMore" />
|
||||||
|
<p-empty v-if="StaticRange.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无产品" />
|
||||||
|
</pb-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { onLoad, onReachBottom } from '@dcloudio/uni-app'
|
||||||
|
import peach from '@/peach'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import { resetPagination } from '@/peach/util'
|
||||||
|
|
||||||
const bgStyle = {
|
const bgStyle = {
|
||||||
backgroundImage: '',
|
backgroundImage: '',
|
||||||
backgroundColor: '',
|
backgroundColor: '',
|
||||||
description: '',
|
description: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const state = ref({
|
||||||
|
pagination: {
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 6
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function emptyList() {
|
||||||
|
resetPagination(state.value.pagination)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSearch() {
|
||||||
|
emptyList()
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
function getList() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadMore() {
|
||||||
|
if (state.value.loadStatus === 'noMore') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.value.pagination.pageNo++
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoad(async (options) => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
|
||||||
|
onReachBottom(() => {
|
||||||
|
loadMore()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -0,0 +1,176 @@
|
||||||
|
<template>
|
||||||
|
<view class="ss-goods-wrap">
|
||||||
|
<view v-if="size === 'lg'" class="lg-goods-card ss-flex ss-col-stretch" :style="[elStyles]" @click="onClick">
|
||||||
|
<image class="lg-img-box" :src="peach.$url.cdn(data.image || data.picUrl)" mode="aspectFill"></image>
|
||||||
|
<view class="lg-goods-content ss-flex-1 ss-flex-col ss-row-between ss-p-b-10 ss-p-t-20">
|
||||||
|
<view>
|
||||||
|
<view v-if="goodsFields.title?.show || goodsFields.name?.show" class="lg-goods-title ss-line-2"
|
||||||
|
:style="[{ color: titleColor }]">
|
||||||
|
{{ data.title || data.name }}
|
||||||
|
</view>
|
||||||
|
<view v-if="goodsFields.subtitle?.show || goodsFields.introduction?.show"
|
||||||
|
class="lg-goods-subtitle ss-m-t-10 ss-line-1"
|
||||||
|
:style="[{ color: subTitleColor, background: subTitleBackground }]">
|
||||||
|
{{ data.subtitle || data.introduction }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<view class="ss-flex ss-col-bottom ss-m-t-10">
|
||||||
|
<view v-if="goodsFields.price?.show" class="lg-goods-price ss-m-r-12 ss-flex ss-col-bottom font-OPPOSANS"
|
||||||
|
:style="[{ color: goodsFields.price.color }]">
|
||||||
|
<text class="ss-font-24">{{ priceUnit }}</text>
|
||||||
|
{{ isArray(data.price) ? fen2yuan(data.price[0]) : fen2yuan(data.price) }}
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
v-if="(goodsFields.original_price?.show || goodsFields.marketPrice?.show) && (data.original_price > 0 || data.marketPrice > 0)"
|
||||||
|
class="goods-origin-price ss-flex ss-col-bottom font-OPPOSANS" :style="[{ color: originPriceColor }]">
|
||||||
|
<text class="price-unit ss-font-20">{{ priceUnit }}</text>
|
||||||
|
<view class="ss-m-l-8">{{ fen2yuan(data.marketPrice) }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="ss-m-t-8 ss-flex ss-col-center ss-flex-wrap">
|
||||||
|
<view class="sales-text">{{ salesAndStock }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<button>详情</button>
|
||||||
|
<button>编辑</button>
|
||||||
|
<button>删除</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { isArray } from 'lodash';
|
||||||
|
import { fen2yuan, formatSales, formatStock } from '@/peach/hooks/useGoods';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
goodsFields: {
|
||||||
|
type: [Array, Object],
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
price: { show: true },
|
||||||
|
stock: { show: true },
|
||||||
|
name: { show: true },
|
||||||
|
introduction: { show: true },
|
||||||
|
marketPrice: { show: true },
|
||||||
|
salesCount: { show: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
topRadius: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
bottomRadius: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
priceUnit: {
|
||||||
|
type: String,
|
||||||
|
default: '¥',
|
||||||
|
},
|
||||||
|
titleColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#333',
|
||||||
|
},
|
||||||
|
subTitleColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#999999',
|
||||||
|
},
|
||||||
|
subTitleBackground: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['click'])
|
||||||
|
|
||||||
|
function onClick() {
|
||||||
|
emits('click')
|
||||||
|
}
|
||||||
|
|
||||||
|
const elStyles = computed(() => {
|
||||||
|
return {
|
||||||
|
background: props.background,
|
||||||
|
'border-top-left-radius': props.topRadius + 'px',
|
||||||
|
'border-top-right-radius': props.topRadius + 'px',
|
||||||
|
'border-bottom-left-radius': props.bottomRadius + 'px',
|
||||||
|
'border-bottom-right-radius': props.bottomRadius + 'px',
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 格式化销量、库存信息
|
||||||
|
const salesAndStock = computed(() => {
|
||||||
|
let text = [];
|
||||||
|
if (props.goodsFields.salesCount?.show) {
|
||||||
|
text.push(formatSales(props.data.sales_show_type, props.data.salesCount));
|
||||||
|
}
|
||||||
|
if (props.goodsFields.stock?.show) {
|
||||||
|
text.push(formatStock(props.data.stock_show_type, props.data.stock));
|
||||||
|
}
|
||||||
|
return text.join(' | ');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.lg-goods-card {
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
background-color: $white;
|
||||||
|
height: 280rpx;
|
||||||
|
|
||||||
|
.lg-img-box {
|
||||||
|
width: 280rpx;
|
||||||
|
height: 280rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg-goods-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333333;
|
||||||
|
// line-height: 36rpx;
|
||||||
|
// width: 410rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg-goods-subtitle {
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #999999;
|
||||||
|
// line-height: 30rpx;
|
||||||
|
// width: 410rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lg-goods-price {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: $red;
|
||||||
|
line-height: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buy-box {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20rpx;
|
||||||
|
right: 20rpx;
|
||||||
|
z-index: 2;
|
||||||
|
width: 120rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
background: linear-gradient(90deg, #fe8900, #ff5e00);
|
||||||
|
border-radius: 25rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { ref } from "vue";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将分转成元
|
||||||
|
*
|
||||||
|
* @param price 分,例如说 100 分
|
||||||
|
* @returns {string} 元,例如说 1.00 元
|
||||||
|
*/
|
||||||
|
export function fen2yuan(price) {
|
||||||
|
return (price / 100.0).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化销量
|
||||||
|
* @param {'exact' | string} type 格式类型:exact=精确值,其它=大致数量
|
||||||
|
* @param {number} num 销量
|
||||||
|
* @return {string} 格式化后的销量字符串
|
||||||
|
*/
|
||||||
|
export function formatSales(type, num) {
|
||||||
|
let prefix = type !== "exact" && num < 10 ? "销量" : "已售";
|
||||||
|
return formatNum(prefix, type, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化库存
|
||||||
|
* @param {'exact' | any} type 格式类型:exact=精确值,其它=大致数量
|
||||||
|
* @param {number} num 销量
|
||||||
|
* @return {string} 格式化后的销量字符串
|
||||||
|
*/
|
||||||
|
export function formatStock(type, num) {
|
||||||
|
return formatNum("库存", type, num);
|
||||||
|
}
|
Loading…
Reference in New Issue