清空代码-初始化yudao

This commit is contained in:
落日晚风
2023-12-18 14:02:47 +08:00
parent aad925ed51
commit 4cb256af6c
102 changed files with 4959 additions and 7836 deletions
+47 -111
View File
@@ -3,35 +3,34 @@
<s-layout title="评价">
<view>
<view v-for="(item, index) in state.orderInfo.items" :key="item.id">
<view v-if="item.btns.includes('comment')">
<view>
<view class="commont-from-wrap">
<!-- 评价商品 -->
<s-goods-item :img="item.goods_image" :title="item.goods_title" :skuText="item.goods_sku_text"
:price="item.goods_price" :num="item.goods_num"></s-goods-item>
<s-goods-item
:img="item.picUrl"
:title="item.spuName"
:skuText="item.properties.map((property) => property.valueName).join(' ')"
:price="item.payPrice"
:num="item.count"
/>
</view>
<view class="form-item">
<!-- 评分 -->
<view class="star-box ss-flex ss-col-center">
<view class="star-title ss-m-r-40">
<!-- {{ rateMap[state.commentList[index].level] }} -->
商品质量
</view>
<uni-rate v-model="state.commentList[index].level" />
<view class="star-title ss-m-r-40">商品质量</view>
<uni-rate v-model="state.commentList[index].descriptionScores" />
</view>
<view class="star-box ss-flex ss-col-center">
<view class="star-title ss-m-r-40">
<!-- {{ rateMap[state.commentList[index].level] }} -->
服务态度
</view>
<uni-rate v-model="state.commentList[index].level2" />
<view class="star-title ss-m-r-40">服务态度</view>
<uni-rate v-model="state.commentList[index].benefitScores" />
</view>
<!-- 评价 -->
<view class="area-box">
<uni-easyinput :inputBorder="false" type="textarea" maxlength="120" autoHeight
v-model="state.commentList[index].content"
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~"></uni-easyinput>
placeholder="宝贝满足你的期待吗?说说你的使用心得,分享给想买的他们吧~" />
<!-- TODO 芋艿:文件上传 -->
<view class="img-box">
<s-uploader v-model:url="state.commentList[index].images" fileMediatype="image"
limit="9" mode="grid" :imageStyles="{ width: '168rpx', height: '168rpx' }" />
@@ -41,6 +40,7 @@
</view>
</view>
</view>
<!-- TODO 芋艿:是否匿名 -->
<su-fixed bottom placeholder>
<view class="foot_box ss-flex ss-row-center ss-col-center">
@@ -54,113 +54,49 @@
<script setup>
import sheep from '@/sheep';
import {
onLoad
} from '@dcloudio/uni-app';
import {
computed,
reactive
} from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { reactive } from 'vue';
import OrderApi from '@/sheep/api/trade/order';
const state = reactive({
orderInfo: {},
commentList: [],
orderId: null
id: null
});
const rateMap = {
1: '糟糕',
2: '差评',
3: '一般',
4: '良好',
5: '好评',
};
async function onSubmit() {
// 对接商品评价
// console.log(state.orderInfo);
// return;
let obj = {
anonymous: false,
benefitScores: state.commentList[0].level2,
content: state.commentList[0].content,
descriptionScores: state.commentList[0].level,
orderItemId: state.commentList[0].item_id,
picUrls: 'https://t7.baidu.com/it/u=2531125946,3055766435&fm=193&f=GIF'
}
const {
code
} = await sheep.$api.order.comment(obj);
if (code === 0) {
sheep.$router.back();
}
// 顺序提交评论
for (const comment of state.commentList) {
await OrderApi.createOrderItemComment(comment);
}
// 都评论好,返回
sheep.$router.back();
}
onLoad(async (options) => {
let id = '';
if (options.orderSN) {
id = options.orderSN;
}
if (options.id) {
id = options.id;
}
if (options.orderId) {
state.orderId = options.orderId
}
if (!options.id) {
sheep.$helper.toast(`缺少订单信息,请检查`);
return
}
state.id = options.id;
const res = await sheep.$api.order.detail(id);
if (res.code === 0) {
let obj = {
10: ['待发货', '等待买家付款', ["apply_refund"]],
30: ['待评价', '等待买家评价', ["express", "comment"]]
}
res.data.status_text = obj[res.data.status][0];
res.data.status_desc = obj[res.data.status][1];
res.data.btns = obj[res.data.status][2];
res.data.address = {
province_name: res.data.receiverAreaName.split(' ')[0],
district_name: res.data.receiverAreaName.split(' ')[2],
city_name: res.data.receiverAreaName.split(' ')[1],
address: res.data.receiverDetailAddress,
consignee: res.data.receiverName,
mobile: res.data.receiverMobile,
}
res.data.pay_fee = res.data.payPrice / 100
res.data.create_time = sheep.$helper.timeFormat(res.data.createTime, 'yyyy-mm-dd hh:MM:ss')
res.data.order_sn = res.data.no
res.data.id = res.data.id
res.data.goods_amount = res.data.totalPrice / 100
res.data.dispatch_amount = res.data.deliveryPrice / 100
res.data.pay_types_text = res.data.payChannelName.split(',')
res.data.items = res.data.items.map(ite => {
return {
...ite,
btns: obj[res.data.status][2],
goods_title: ite.spuName,
goods_num: ite.count,
goods_price: ite.price / 100,
goods_image: ite.picUrl,
goods_sku_text: ite.properties.reduce((it0, it1) => it0 + it1.valueName + ' ', '')
}
})
if (res.data.btns.includes('comment')) {
state.orderInfo = res.data;
state.orderInfo.items.forEach((item) => {
if (item.btns.includes('comment')) {
state.commentList.push({
item_id: item.id,
level: 5,
content: '',
images: [],
});
}
});
console.log(state.orderInfo.items, '循环')
return;
}
}
sheep.$helper.toast('无待评价订单');
const { code, data } = await sheep.$api.order.detail(state.id);
if (code !== 0) {
sheep.$helper.toast('无待评价订单');
return
}
// 处理评论
data.items.forEach((item) => {
state.commentList.push({
anonymous: false,
orderItemId: item.id,
descriptionScores: 5,
benefitScores: 5,
content: '',
picUrls: []
});
});
state.orderInfo = data;
});
</script>
@@ -1,115 +0,0 @@
<template>
<view>
<detail-cell
v-if="modelValue.length > 0"
label="参数"
:value="state.paramsTitle"
@click="state.show = true"
></detail-cell>
<su-popup :show="state.show" round="10" :showClose="true" @close="close">
<view class="ss-modal-box bg-white">
<view class="modal-header">产品参数</view>
<scroll-view
class="modal-content ss-p-t-50"
scroll-y="true"
:scroll-with-animation="true"
:show-scrollbar="false"
@touchmove.stop
>
<view class="sale-item ss-flex ss-col-top" v-for="item in modelValue" :key="item.title">
<view class="item-title">{{ item.title }}</view>
<view class="item-value">{{ item.content }}</view>
</view>
</scroll-view>
<view class="modal-footer ss-flex ss-row-center ss-m-b-20">
<button class="ss-reset-button save-btn ui-Shadow-Main" @tap="state.show = false"
>确定</button
>
</view>
</view>
</su-popup>
</view>
</template>
<script setup>
import { reactive, computed } from 'vue';
import detailCell from './detail-cell.vue';
const props = defineProps({
modelValue: {
type: Object,
default() {
return [];
},
},
});
const state = reactive({
show: false,
paramsTitle: computed(() => {
let titleArray = [];
props.modelValue.map((item) => {
titleArray.push(item.title);
});
return titleArray.join(' · ');
}),
});
function close() {
state.show = false;
}
</script>
<style lang="scss" scoped>
.ss-modal-box {
border-radius: 30rpx 30rpx 0 0;
max-height: 730rpx;
.modal-header {
position: relative;
padding: 30rpx 20rpx 40rpx;
font-size: 36rpx;
font-weight: bold;
}
.modal-content {
padding: 0 30rpx;
max-height: 500rpx;
box-sizing: border-box;
.sale-item {
margin-bottom: 24rpx;
padding-bottom: 24rpx;
border-bottom: 2rpx solid rgba(#dfdfdf, 0.4);
.item-title {
font-size: 28rpx;
font-weight: 500;
line-height: 42rpx;
width: 120rpx;
white-space: normal;
}
.item-value {
font-size: 26rpx;
font-weight: 400;
color: $dark-9;
line-height: 42rpx;
flex: 1;
margin-left: 20rpx;
}
}
}
.modal-footer {
height: 120rpx;
.save-btn {
width: 710rpx;
height: 80rpx;
border-radius: 40rpx;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
color: $white;
}
}
}
</style>
@@ -1,121 +0,0 @@
<template>
<view>
<detail-cell
v-if="modelValue.length > 0"
label="保障"
:value="state.paramsTitle"
@click="state.show = true"
>
</detail-cell>
<su-popup :show="state.show" round="10" :showClose="true" @close="state.show = false">
<view class="ss-modal-box">
<view class="modal-header">服务保障</view>
<scroll-view
class="modal-content"
scroll-y="true"
:scroll-with-animation="true"
:show-scrollbar="false"
@touchmove.stop
>
<view class="sale-item ss-flex ss-col-top" v-for="item in modelValue" :key="item.id">
<image
class="title-icon ss-m-r-14"
:src="sheep.$url.cdn(item.image)"
mode="aspectFill"
></image>
<view class="title-box">
<view class="item-title ss-m-b-20">{{ item.name }}</view>
<view class="item-value">{{ item.description }}</view>
</view>
</view>
</scroll-view>
<view class="modal-footer ss-flex ss-row-center ss-m-b-20">
<button class="ss-reset-button save-btn ui-Shadow-Main" @tap="state.show = false"
>确定</button
>
</view>
</view>
</su-popup>
</view>
</template>
<script setup>
import { reactive, computed } from 'vue';
import sheep from '@/sheep';
import detailCell from './detail-cell.vue';
const props = defineProps({
modelValue: {
type: Object,
default() {},
},
});
const state = reactive({
show: false,
paramsTitle: computed(() => {
let nameArray = [];
props.modelValue.map((item) => {
nameArray.push(item.name);
});
return nameArray.join(' · ');
}),
});
</script>
<style lang="scss" scoped>
.ss-modal-box {
border-radius: 30rpx 30rpx 0 0;
max-height: 730rpx;
.modal-header {
position: relative;
padding: 30rpx 20rpx 40rpx;
font-size: 36rpx;
font-weight: bold;
}
.modal-content {
padding: 0 30rpx;
max-height: 500rpx;
box-sizing: border-box;
.sale-item {
margin-bottom: 44rpx;
.title-icon {
width: 36rpx;
height: 36rpx;
}
.title-box{
flex: 1;
}
.item-title {
font-size: 28rpx;
font-weight: 500;
line-height: normal;
}
.item-value {
font-size: 26rpx;
font-weight: 400;
color: $dark-9;
line-height: 42rpx;
}
}
}
.modal-footer {
height: 120rpx;
background-color: #fff;
.save-btn {
width: 710rpx;
height: 80rpx;
border-radius: 40rpx;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
color: $white;
}
}
}
</style>
@@ -1,3 +1,4 @@
<!-- 商品详情:cell 组件 -->
<template>
<view class="detail-cell-wrap ss-flex ss-col-center ss-row-between" @tap="onClick">
<view class="label-text">{{ label }}</view>
@@ -13,7 +14,6 @@
* 详情 cell
*
*/
const props = defineProps({
label: {
type: String,
@@ -1,3 +1,4 @@
<!-- 商品详情:描述卡片 -->
<template>
<view class="detail-content-card bg-white ss-m-x-20 ss-p-t-20">
<view class="card-header ss-flex ss-col-center ss-m-b-30 ss-m-l-20">
@@ -5,7 +6,7 @@
<view class="title ss-m-l-20 ss-m-r-20">详情</view>
</view>
<view class="card-content">
<mp-html :content="content"></mp-html>
<mp-html :content="content" />
</view>
</view>
</template>
@@ -1,3 +1,4 @@
<!-- 商品详情:商品/评价/详情的 nav -->
<template>
<su-fixed alway :bgStyles="{ background: '#fff' }" :val="0" noNav opacity :placeholder="false">
<su-status-bar />
@@ -1,3 +1,4 @@
<!-- 秒杀商品:抢购进度 -->
<template>
<view class="ss-flex ss-col-center">
<view class="progress-title ss-m-r-10"> 已抢{{ percent }}% </view>
+22 -24
View File
@@ -1,3 +1,4 @@
<!-- 商品详情的底部导航 -->
<template>
<su-fixed bottom placeholder bg="bg-white">
<view class="ui-tabbar-box">
@@ -12,7 +13,7 @@
class="item-icon"
:src="sheep.$url.static('/static/img/shop/goods/collect_1.gif')"
mode="aspectFit"
></image>
/>
<view class="item-title">已收藏</view>
</block>
<block v-else>
@@ -20,7 +21,7 @@
class="item-icon"
:src="sheep.$url.static('/static/img/shop/goods/collect_0.png')"
mode="aspectFit"
></image>
/>
<view class="item-title">收藏</view>
</block>
</view>
@@ -33,7 +34,7 @@
class="item-icon"
:src="sheep.$url.static('/static/img/shop/goods/message.png')"
mode="aspectFit"
></image>
/>
<view class="item-title">客服</view>
</view>
<view
@@ -45,7 +46,7 @@
class="item-icon"
:src="sheep.$url.static('/static/img/shop/goods/share.png')"
mode="aspectFit"
></image>
/>
<view class="item-title">分享</view>
</view>
<slot></slot>
@@ -63,13 +64,11 @@
* @property {String} ui - 自定义样式Class
* @property {Boolean} noFixed - 是否定位
* @property {Boolean} topRadius - 上圆角
*
*
*/
import { computed, reactive } from 'vue';
import { reactive } from 'vue';
import sheep from '@/sheep';
import { showShareModal } from '@/sheep/hooks/useModal';
import FavoriteApi from '@/sheep/api/product/favorite';
// 数据
const state = reactive({});
@@ -114,25 +113,24 @@
default: true,
},
});
const elStyles = computed(() => {
return {
'border-top-left-radius': props.topRadius + 'rpx',
'border-top-right-radius': props.topRadius + 'rpx',
overflow: 'hidden',
};
});
const tabbarheight = (e) => {
uni.setStorageSync('tabbar', e);
};
async function onFavorite() {
const { error } = await sheep.$api.user.favorite.do(props.modelValue.id);
if (error === 0) {
if (props.modelValue.favorite) {
props.modelValue.favorite = 0;
} else {
props.modelValue.favorite = 1;
// 情况一:取消收藏
if (props.modelValue.favorite) {
const { code } = await FavoriteApi.deleteFavorite(props.modelValue.id);
if (code !== 0) {
return
}
sheep.$helper.toast('取消收藏');
props.modelValue.favorite = false;
// 情况二:添加收藏
} else {
const { code } = await FavoriteApi.createFavorite(props.modelValue.id);
if (code !== 0) {
return
}
sheep.$helper.toast('收藏成功');
props.modelValue.favorite = true;
}
}
@@ -1,4 +1,4 @@
<!-- 页面 -->
<!-- 页面;暂时没用到 -->
<template>
<view class="list-goods-card ss-flex-col" @tap="onClick">
<view class="md-img-box">
@@ -1,3 +1,4 @@
<!-- 页面;暂时没用到 -->
<template>
<su-fixed
alway
+2 -8
View File
@@ -86,10 +86,6 @@
:skus="state.goodsInfo.skus"
@tap="state.showSelectSku = true"
/>
<!-- 服务 -->
<detail-cell-service v-model="state.goodsInfo.service" />
<!-- 参数 -->
<detail-cell-params v-model="state.goodsInfo.params" />
<!-- 玩法 -->
<detail-cell
v-if="state.goodsInfo.activity.richtext_id > 0"
@@ -173,15 +169,13 @@
</template>
<script setup>
import { reactive, getCurrentInstance, computed, ref } from 'vue';
import { reactive, computed, ref } from 'vue';
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
import sheep from '@/sheep';
import { isEmpty } from 'lodash';
import detailNavbar from './components/detail/detail-navbar.vue';
import detailCell from './components/detail/detail-cell.vue';
import detailCellSku from './components/detail/detail-cell-sku.vue';
import detailCellService from './components/detail/detail-cell-service.vue';
import detailCellParams from './components/detail/detail-cell-params.vue';
import detailTabbar from './components/detail/detail-tabbar.vue';
import detailSkeleton from './components/detail/detail-skeleton.vue';
import detailCommentCard from './components/detail/detail-comment-card.vue';
@@ -209,7 +203,7 @@
grouponId: 0, // 团购ID
grouponType: '', // 团购类型
grouponNum: 0, // 团购人数
grouponAction: 'create', // 团购操作
grouponAction: 'create', // 团购操作
});
// 商品主价格
+52 -45
View File
@@ -56,9 +56,6 @@
<view class="detail-cell-card detail-card ss-flex-col">
<detail-cell-sku v-model="state.selectedSku.goods_sku_text" :sku="state.selectedSku"
@tap="state.showSelectSku = true" />
<!-- TODO 芋艿:可能暂时不考虑使用 -->
<detail-cell-service v-if="state.goodsInfo.service" v-model="state.goodsInfo.service" />
<detail-cell-params v-if="state.goodsInfo.params" v-model="state.goodsInfo.params" />
</view>
<!-- 规格与数量弹框 -->
@@ -91,11 +88,11 @@
<!-- 优惠劵弹窗 -->
<s-coupon-get v-model="state.couponInfo" :show="state.showModel" @close="state.showModel = false"
@get="onGet" />
@get="onGet" />
<!-- 满减送/限时折扣活动弹窗 -->
<s-activity-pop v-model="state.activityInfo" :show="state.showActivityModel"
@close="state.showActivityModel = false" />
@close="state.showActivityModel = false" />
</block>
</s-layout>
</view>
@@ -113,23 +110,16 @@
import sheep from '@/sheep';
import CouponApi from '@/sheep/api/promotion/coupon';
import ActivityApi from '@/sheep/api/promotion/activity';
import {
formatSales,
formatGoodsSwiper,
fen2yuan,
} from '@/sheep/hooks/useGoods';
import FavoriteApi from '@/sheep/api/product/favorite';
import { formatSales, formatGoodsSwiper, fen2yuan } from '@/sheep/hooks/useGoods';
import detailNavbar from './components/detail/detail-navbar.vue';
import detailCellSku from './components/detail/detail-cell-sku.vue';
import detailCellService from './components/detail/detail-cell-service.vue';
import detailCellParams from './components/detail/detail-cell-params.vue';
import detailTabbar from './components/detail/detail-tabbar.vue';
import detailSkeleton from './components/detail/detail-skeleton.vue';
import detailCommentCard from './components/detail/detail-comment-card.vue';
import detailContentCard from './components/detail/detail-content-card.vue';
import detailActivityTip from './components/detail/detail-activity-tip.vue';
import {
isEmpty
} from 'lodash';
import { isEmpty } from 'lodash';
onPageScroll(() => {});
@@ -153,21 +143,30 @@
// 添加购物车 TODO 芋艿:待测试
function onAddCart(e) {
if (!e.id) {
sheep.$helper.toast('请选择商品规格');
return;
}
sheep.$store('cart').add(e);
}
// 立即购买 TODO 芋艿:待测试
// 立即购买
function onBuy(e) {
sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({
order_type: 'goods',
goods_list: [{
goods_id: e.goods_id,
goods_num: e.goods_num,
goods_sku_price_id: e.id,
}, ],
}),
});
if (!state.selectedSku.id) {
sheep.$helper.toast('请选择商品规格');
return;
}
sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({
items: [{
skuId: state.selectedSku.id,
count: 1
}],
// TODO 芋艿:后续清理掉这 2 参数
deliveryType: 1,
pointStatus: false,
}),
});
}
// 营销活动 TODO 芋艿:待测试
@@ -178,18 +177,16 @@
// 立即领取 TODO 芋艿:待测试
async function onGet(id) {
const {
error,
msg
} = await sheep.$api.coupon.get(id);
if (error === 0) {
uni.showToast({
title: msg,
});
setTimeout(() => {
getCoupon();
}, 1000);
}
const { code } = await CouponApi.takeCoupon(id);
if (code !== 0) {
return;
}
uni.showToast({
title: '领取成功',
});
setTimeout(() => {
getCoupon();
}, 1000);
}
// TODO 芋艿:待测试
@@ -213,7 +210,14 @@
}, );
});
onLoad(async (options) => {
async function getCoupon() {
const { code, data } = await CouponApi.getCouponTemplateList(state.goodsId, 2, 10);
if (code === 0) {
state.couponInfo = data;
}
}
onLoad((options) => {
// 非法参数
if (!options.id) {
state.goodsInfo = null;
@@ -230,15 +234,18 @@
// 加载到商品
state.skeletonLoading = false;
state.goodsInfo = res.data;
// 加载是否收藏
FavoriteApi.isFavoriteExists(state.goodsId, 'goods').then((res) => {
if (res.code !== 0) {
return;
}
state.goodsInfo.favorite = res.data;
});
});
// 2. 加载优惠劵信息
CouponApi.getCouponTemplateList(state.goodsId, 2, 10).then((res) => {
if (res.code !== 0) {
return;
}
state.couponInfo = res.data;
});
getCoupon();
// 3. 加载营销活动信息
ActivityApi.getActivityListBySpuId(state.goodsId).then((res) => {
+115 -103
View File
@@ -6,11 +6,11 @@
<view class="ss-flex">
<view class="ss-flex-1">
<su-tabs :list="state.tabList" :scrollable="false" @change="onTabsChange"
:current="state.currentTab"></su-tabs>
:current="state.currentTab" />
</view>
<view class="list-icon" @tap="state.iconStatus = !state.iconStatus">
<text v-if="state.iconStatus" class="sicon-goods-list"></text>
<text v-else class="sicon-goods-card"></text>
<text v-if="state.iconStatus" class="sicon-goods-list" />
<text v-else class="sicon-goods-card" />
</view>
</view>
</su-sticky>
@@ -20,38 +20,59 @@
:zIndex="10" @close="state.showFilter = false">
<view class="filter-list-box">
<view class="filter-item" v-for="(item, index) in state.tabList[state.currentTab].list"
:key="item.value" :class="[{ 'filter-item-active': index == state.curFilter }]"
:key="item.value" :class="[{ 'filter-item-active': index === state.curFilter }]"
@tap="onFilterItem(index)">
{{ item.label }}
</view>
</view>
</su-popup>
<!-- 情况一:单列布局 -->
<view v-if="state.iconStatus && state.pagination.total > 0" class="goods-list ss-m-t-20">
<view class="ss-p-l-20 ss-p-r-20 ss-m-b-20" v-for="item in state.pagination.data" :key="item.id">
<s-goods-column class="" size="lg" :data="item" :topRadius="10" :bottomRadius="10"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"></s-goods-column>
<view class="ss-p-l-20 ss-p-r-20 ss-m-b-20" v-for="item in state.pagination.list" :key="item.id">
<s-goods-column
class=""
size="lg"
:data="item"
:topRadius="10"
:bottomRadius="10"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
/>
</view>
</view>
<view v-if="!state.iconStatus && state.pagination.total > 0"
<!-- 情况二:双列布局 -->
<view v-if="!state.iconStatus && state.pagination.total > 0"
class="ss-flex ss-flex-wrap ss-p-x-20 ss-m-t-20 ss-col-top">
<view class="goods-list-box">
<view class="left-list" v-for="item in state.leftGoodsList" :key="item.id">
<s-goods-column class="goods-md-box" size="md" :data="item" :topRadius="10" :bottomRadius="10"
<s-goods-column
class="goods-md-box"
size="md"
:data="item"
:topRadius="10"
:bottomRadius="10"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
@getHeight="mountMasonry($event, 'left')">
@getHeight="mountMasonry($event, 'left')"
>
<template v-slot:cart>
<button class="ss-reset-button cart-btn"> </button>
<button class="ss-reset-button cart-btn" />
</template>
</s-goods-column>
</view>
</view>
<view class="goods-list-box">
<view class="right-list" v-for="item in state.rightGoodsList" :key="item.id">
<s-goods-column class="goods-md-box" size="md" :topRadius="10" :bottomRadius="10" :data="item"
<s-goods-column
class="goods-md-box"
size="md"
:topRadius="10"
:bottomRadius="10"
:data="item"
@click="sheep.$router.go('/pages/goods/index', { id: item.id })"
@getHeight="mountMasonry($event, 'right')">
@getHeight="mountMasonry($event, 'right')"
>
<template v-slot:cart>
<button class="ss-reset-button cart-btn"> </button>
<button class="ss-reset-button cart-btn" />
</template>
</s-goods-column>
</view>
@@ -59,54 +80,43 @@
</view>
<uni-load-more v-if="state.pagination.total > 0" :status="state.loadStatus" :content-text="{
contentdown: '上拉加载更多',
}" @tap="loadmore" />
<s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品">
</s-empty>
}" @tap="loadMore" />
<s-empty v-if="state.pagination.total === 0" icon="/static/soldout-empty.png" text="暂无商品" />
</s-layout>
</template>
<script setup>
import {
reactive
} from 'vue';
import { reactive } from 'vue';
import {
onLoad,
onReachBottom
} from '@dcloudio/uni-app';
import sheep from '@/sheep';
import _ from 'lodash';
import { resetPagination } from '@/sheep/util';
const sys_navBar = sheep.$platform.navbar;
const emits = defineEmits(['close', 'change']);
const pagination = {
data: [],
current_page: 1,
total: 1,
last_page: 1,
};
const state = reactive({
pagination: {
data: [],
current_page: 1,
total: 1,
last_page: 1,
list: [],
total: 0,
pageNo: 1,
pageSize: 6,
},
// currentSort: 'weigh',
// currentOrder: 'desc',
currentTab: 0,
filterParams: {},
curFilter: 0,
currentSort: undefined,
currentOrder: undefined,
currentTab: 0, // 当前选中的 tab
curFilter: 0, // 当前选中的 list 筛选项
showFilter: false,
iconStatus: false,
categoryId: 0,
iconStatus: false, // true - 单列布局;false - 双列布局
keyword: '',
categoryId: 0,
tabList: [{
name: '综合推荐',
// value: '',
list: [{
label: '综合推荐',
// sort: '',
// order: true,
label: '综合推荐'
},
{
label: '价格升序',
@@ -123,18 +133,17 @@
{
name: '销量',
sort: 'salesCount',
order: false,
// value: 'salesCount',
order: false
},
{
name: '新品优先',
// value: 'create_time',
value: 'createTime',
order: false
},
],
loadStatus: '',
keyword: '',
leftGoodsList: [],
rightGoodsList: [],
leftGoodsList: [], // 双列布局 - 左侧商品
rightGoodsList: [], // 双列布局 - 右侧商品
});
// 加载瀑布流
@@ -142,8 +151,11 @@
let leftHeight = 0;
let rightHeight = 0;
// 处理双列布局 leftGoodsList + rightGoodsList
function mountMasonry(height = 0, where = 'left') {
if (!state.pagination.data[count]) return;
if (!state.pagination.list[count]) {
return;
}
if (where === 'left') {
leftHeight += height;
@@ -151,110 +163,110 @@
rightHeight += height;
}
if (leftHeight <= rightHeight) {
state.leftGoodsList.push(state.pagination.data[count]);
state.leftGoodsList.push(state.pagination.list[count]);
} else {
state.rightGoodsList.push(state.pagination.data[count]);
state.rightGoodsList.push(state.pagination.list[count]);
}
count++;
}
// 清空列表
function emptyList() {
state.pagination = pagination
state.leftGoodsList = [];
resetPagination(state.pagination);
state.leftGoodsList = [];
state.rightGoodsList = [];
count = 0;
leftHeight = 0;
rightHeight = 0;
}
//搜索
// 搜索
function onSearch(e) {
state.keyword = e;
emptyList();
getList(state.currentSort, state.currentOrder, state.categoryId, e);
getList(state.currentSort, state.currentOrder);
}
// 点击
function onTabsChange(e) {
// 如果点击的是【综合推荐】,则直接展开或者收起筛选项
if (state.tabList[e.index].list) {
state.currentTab = e.index;
state.showFilter = !state.showFilter;
return;
} else {
state.showFilter = false;
}
state.showFilter = false;
// 如果点击的是【销量】或者【新品优先】,则直接切换 tab
if (e.index === state.currentTab) {
return;
} else {
state.currentTab = e.index;
}
state.currentTab = e.index;
state.currentSort = e.sort;
state.currentOrder = e.order;
emptyList();
console.log(e, '6666')
getList(e.sort, e.order, state.categoryId, state.keyword);
getList(e.sort, e.order);
}
// 点击筛选项
// 点击 tab 的 list 筛选项
const onFilterItem = (val) => {
console.log(val)
if (
state.currentSort === state.tabList[0].list[val].sort &&
state.currentOrder === state.tabList[0].list[val].order
) {
// 如果点击的是当前的筛选项,则直接收起筛选项,不要加载数据
// 这里选择 tabList[0] 的原因,是目前只有它有 list
if (state.currentSort === state.tabList[0].list[val].sort
&& state.currentOrder === state.tabList[0].list[val].order) {
state.showFilter = false;
return;
}
state.showFilter = false;
// 设置筛选条件
state.curFilter = val;
state.tabList[0].name = state.tabList[0].list[val].label;
state.currentSort = state.tabList[0].list[val].sort;
state.currentOrder = state.tabList[0].list[val].order;
emptyList();
getList(state.currentSort, state.currentOrder, state.categoryId, state.keyword);
state.showFilter = false;
};
// 清空 + 加载数据
emptyList();
getList();
}
async function getList(Sort, Order, categoryId, keyword, page = 1, list_rows = 6) {
async function getList() {
state.loadStatus = 'loading';
const res = await sheep.$api.goods.list({
sortField: Sort,
sortAsc: Order,
category_id: !keyword ? categoryId : '',
pageSize: list_rows,
keyword: keyword,
pageNo: page,
const { code, data } = await sheep.$api.goods.list({
pageNo: state.pagination.pageNo,
pageSize: state.pagination.pageSize,
sortField: state.currentSort,
sortAsc: state.currentOrder,
categoryId: state.categoryId,
keyword: state.keyword,
});
if (res.code === 0) {
let couponList = _.concat(state.pagination.data, res.data.list);
state.pagination = {
...res.data,
data: couponList,
};
mountMasonry();
if (state.pagination.current_page < state.pagination.last_page) {
state.loadStatus = 'more';
} else {
state.loadStatus = 'noMore';
}
}
if (code !== 0) {
return;
}
state.pagination.list = _.concat(state.pagination.list, data.list)
state.pagination.total = data.total;
state.loadStatus = state.pagination.list.length < state.pagination.total ? 'more' : 'noMore';
mountMasonry();
}
// 加载更多
function loadmore() {
if (state.loadStatus !== 'noMore') {
getList(
state.currentSort,
state.currentOrder,
state.categoryId,
state.keyword,
state.pagination.current_page + 1,
);
}
function loadMore() {
if (state.loadStatus === 'noMore') {
return;
}
state.pagination.pageNo++;
getList(state.currentSort, state.currentOrder);
}
onLoad((options) => {
state.categoryId = options.categoryId;
state.keyword = options.keyword;
getList(state.currentSort, state.currentOrder, state.categoryId, state.keyword);
getList(state.currentSort, state.currentOrder);
});
// 上拉加载更多
onReachBottom(() => {
loadmore();
loadMore();
});
</script>
-368
View File
@@ -1,368 +0,0 @@
<template>
<view>
<s-layout :onShareAppMessage="state.shareInfo" navbar="goods">
<!-- 标题栏 -->
<detailNavbar />
<detailSkeleton v-if="state.skeletonLoading" />
<!-- 空置页 -->
<s-empty
v-else-if="state.goodsInfo === null"
text="商品不存在或已下架"
icon="/static/soldout-empty.png"
showAction
actionText="再逛逛"
actionUrl="/pages/goods/list"
/>
<block v-else>
<!-- 商品轮播图 -->
<su-swiper
class="ss-m-b-14 detail-swiper-selector"
isPreview
:list="state.goodsSwiper"
dotStyle="tag"
imageMode="widthFix"
dotCur="bg-mask-40"
:seizeHeight="750"
/>
<!-- 价格+标题 -->
<view class="title-card detail-card ss-p-y-40 ss-p-x-20">
<view class="ss-flex ss-row-between ss-col-center ss-m-b-18">
<view class="price-box ss-flex ss-col-bottom">
<view v-if="goodsPrice.price > 0" class="price-text"> ¥{{ goodsPrice.price }} </view>
<text v-if="goodsPrice.price > 0 && goodsPrice.score > 0">+</text>
<image
:src="sheep.$url.static('/static/img/shop/goods/score1.svg')"
class="score-img"
></image>
<view class="score-text ss-m-r-16">
{{ goodsPrice.score }}
</view>
</view>
<view class="sales-text">
{{ formatExchange(state.goodsInfo.sales_show_type, state.goodsInfo.sales) }}
</view>
</view>
<view class="origin-price-text ss-m-b-60" v-if="state.goodsInfo.original_price">
原价:¥{{ state.selectedSkuPrice.original_price || state.goodsInfo.original_price }}
</view>
<view class="title-text ss-line-2 ss-m-b-6">{{ state.goodsInfo.title }}</view>
<view class="subtitle-text ss-line-1">{{ state.goodsInfo.subtitle }}</view>
</view>
<!-- 功能卡片 -->
<view class="detail-cell-card detail-card ss-flex-col">
<detail-cell-sku
v-model="state.selectedSkuPrice.goods_sku_text"
:skus="state.goodsInfo.skus"
@tap="state.showSelectSku = true"
/>
<detail-cell-service v-model="state.goodsInfo.service" />
<detail-cell-params v-model="state.goodsInfo.params" />
</view>
<!-- 规格与数量弹框 -->
<s-select-sku
:goodsInfo="state.goodsInfo"
:show="state.showSelectSku"
:isScore="true"
@addCart="onAddCart"
@buy="onBuy"
@change="onSkuChange"
@close="state.showSelectSku = false"
/>
<!-- 评价 -->
<view class="detail-comment-selector">
<detail-comment-card :goodsId="state.goodsId" />
</view>
<!-- 详情 -->
<view class="detail-content-selector"></view>
<detail-content-card :content="state.goodsInfo.content" />
<!-- 详情tabbar -->
<detail-tabbar v-model="state.goodsInfo" :shareIcon="false" :collectIcon="false">
<!-- TODO: 缺货中 已售罄 判断 设计-->
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-if="state.goodsInfo.stock > 0">
<button class="ss-reset-button buy-btn" @tap="state.showSelectSku = true">
立即兑换
</button>
</view>
<view class="buy-box ss-flex ss-col-center ss-p-r-20" v-else>
<button class="ss-reset-button disabled-btn" disabled> 已兑完 </button>
</view>
</detail-tabbar>
</block>
</s-layout>
</view>
</template>
<script setup>
import { reactive, computed } from 'vue';
import { onLoad, onPageScroll } from '@dcloudio/uni-app';
import sheep from '@/sheep';
import { isEmpty } from 'lodash';
import { formatExchange, formatGoodsSwiper } from '@/sheep/hooks/useGoods';
import detailNavbar from './components/detail/detail-navbar.vue';
import detailCellSku from './components/detail/detail-cell-sku.vue';
import detailCellService from './components/detail/detail-cell-service.vue';
import detailCellParams from './components/detail/detail-cell-params.vue';
import detailTabbar from './components/detail/detail-tabbar.vue';
import detailSkeleton from './components/detail/detail-skeleton.vue';
import detailCommentCard from './components/detail/detail-comment-card.vue';
import detailContentCard from './components/detail/detail-content-card.vue';
const headerBg = sheep.$url.css('/static/img/shop/goods/score-bg.png');
const seckillBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.png');
const grouponBg = sheep.$url.css('/static/img/shop/goods/seckill-tip-bg.png');
onPageScroll(() => {});
const state = reactive({
goodsId: 0,
skeletonLoading: true,
goodsInfo: {},
showSelectSku: false,
goodsSwiper: [],
selectedSkuPrice: {},
shareInfo: {},
showModel: false,
total: 0,
couponInfo: [],
});
const goodsPrice = computed(() => {
let price, score;
if (isEmpty(state.selectedSkuPrice)) {
price = state.goodsInfo.price[0];
score = state.goodsInfo.score || 0;
} else {
price = state.selectedSkuPrice.price;
score = state.selectedSkuPrice.score || 0;
}
return { price, score };
});
// 规格变更
function onSkuChange(e) {
state.selectedSkuPrice = e;
}
// 格式化价格
function formatPrice(e) {
if (Number(e[0]) > 0) {
return e.length === 1 ? e[0] : e.join('~');
} else {
return '';
}
}
// 添加购物车
function onAddCart(e) {
sheep.$store('cart').add(e);
}
// 立即购买
function onBuy(e) {
sheep.$router.go('/pages/order/confirm', {
data: JSON.stringify({
order_type: 'score',
goods_list: [
{
goods_id: e.goods_id,
goods_num: e.goods_num,
goods_sku_price_id: e.id,
},
],
}),
});
}
onLoad((options) => {
// 非法参数
if (!options.id) {
state.goodsInfo = null;
return;
}
state.goodsId = options.id;
// 加载商品信息
sheep.$api.app.scoreShop.detail(state.goodsId).then((res) => {
state.skeletonLoading = false;
if (res.error === 0) {
state.goodsInfo = res.data;
state.goodsSwiper = formatGoodsSwiper(state.goodsInfo.images);
} else {
// 未找到商品
state.goodsInfo = null;
}
});
});
</script>
<style lang="scss" scoped>
.detail-card {
background-color: #ffff;
margin: 14rpx 20rpx;
border-radius: 10rpx;
overflow: hidden;
}
// 价格标题卡片
.title-card {
width: 710rpx;
box-sizing: border-box;
background-size: 100% 100%;
border-radius: 10rpx;
background-image: v-bind(headerBg);
background-repeat: no-repeat;
.price-box {
.score-img {
width: 36rpx;
height: 36rpx;
margin: 0 4rpx;
}
.score-text {
font-size: 42rpx;
font-weight: 500;
color: #ff3000;
line-height: 36rpx;
font-family: OPPOSANS;
}
.price-text {
font-size: 42rpx;
font-weight: 500;
color: #ff3000;
line-height: 36rpx;
font-family: OPPOSANS;
}
}
.origin-price-text {
font-size: 26rpx;
font-weight: 400;
text-decoration: line-through;
color: $gray-c;
font-family: OPPOSANS;
}
.sales-text {
font-size: 26rpx;
font-weight: 500;
color: $gray-c;
}
.discounts-box {
.discounts-tag {
padding: 4rpx 10rpx;
font-size: 24rpx;
font-weight: 500;
border-radius: 4rpx;
color: var(--ui-BG-Main);
// background: rgba(#2aae67, 0.05);
background: var(--ui-BG-Main-tag);
}
.discounts-title {
font-size: 24rpx;
font-weight: 500;
color: var(--ui-BG-Main);
line-height: normal;
}
.cicon-forward {
color: var(--ui-BG-Main);
font-size: 24rpx;
line-height: normal;
margin-top: 4rpx;
}
}
.title-text {
font-size: 30rpx;
font-weight: bold;
line-height: 42rpx;
}
.subtitle-text {
font-size: 26rpx;
font-weight: 400;
color: $dark-9;
line-height: 42rpx;
}
}
// 购买
.buy-box {
.buy-btn {
width: 630rpx;
height: 80rpx;
border-radius: 40rpx;
background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
color: $white;
}
.disabled-btn {
width: 630rpx;
height: 80rpx;
border-radius: 40rpx;
background: #999999;
color: $white;
}
}
//秒杀卡片
.seckill-box {
background: v-bind(seckillBg) no-repeat;
background-size: 100% 100%;
}
.groupon-box {
background: v-bind(grouponBg) no-repeat;
background-size: 100% 100%;
}
//活动卡片
.activity-box {
width: 100%;
height: 80rpx;
box-sizing: border-box;
margin-bottom: 10rpx;
.activity-title {
font-size: 26rpx;
font-weight: 500;
color: #ffffff;
line-height: 42rpx;
.activity-icon {
width: 38rpx;
height: 38rpx;
}
}
.activity-go {
width: 70rpx;
height: 32rpx;
background: #ffffff;
border-radius: 16rpx;
font-weight: 500;
color: #ff6000;
font-size: 24rpx;
line-height: normal;
}
}
.model-box {
height: 60vh;
.model-content {
height: 56vh;
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #333333;
}
.subtitle {
font-size: 26rpx;
font-weight: 500;
color: #333333;
}
}
</style>
-4
View File
@@ -73,8 +73,6 @@
:skus="state.goodsInfo.skus"
@tap="state.showSelectSku = true"
/>
<detail-cell-service v-model="state.goodsInfo.service" />
<detail-cell-params v-model="state.goodsInfo.params" />
</view>
<!-- 规格与数量弹框 -->
<s-select-seckill-sku
@@ -145,8 +143,6 @@
import { useDurationTime, formatGoodsSwiper, formatPrice } from '@/sheep/hooks/useGoods';
import detailNavbar from './components/detail/detail-navbar.vue';
import detailCellSku from './components/detail/detail-cell-sku.vue';
import detailCellService from './components/detail/detail-cell-service.vue';
import detailCellParams from './components/detail/detail-cell-params.vue';
import detailTabbar from './components/detail/detail-tabbar.vue';
import detailSkeleton from './components/detail/detail-skeleton.vue';
import detailCommentCard from './components/detail/detail-comment-card.vue';